[rubygems/rubygems] Auto-heal on corrupted lockfile with missing deps
Following up on https://github.com/rubygems/rubygems/pull/6355, which turned a crash into a nicer error message, this commit auto-heals the corrupt lockfile instead. In this particular case (a corrupt Gemfile.lock with missing dependencies) the LazySpecification will not have accurate dependency information, we have to materialize the SpecSet to determine there are missing dependencies. We've already got a way to handle this, via `SpecSet#incomplete_specs`, but it wasn't quite working for this case because we'd get to `@incomplete_specs += lookup[name]` and `lookup[name]` would be empty for the dependency. With this commit we catch it a bit earlier, marking the parent spec containing the missing dependency as incomplete. https://github.com/rubygems/rubygems/commit/486ecb8f20
This commit is contained in:
parent
c43fbe4ebd
commit
62b3bcba5e
@ -47,13 +47,6 @@ module Bundler
|
|||||||
dependencies.all? {|d| installed_specs.include? d.name }
|
dependencies.all? {|d| installed_specs.include? d.name }
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check whether spec's dependencies are missing, which can indicate a
|
|
||||||
# corrupted lockfile
|
|
||||||
def dependencies_missing?(all_specs)
|
|
||||||
spec_names = all_specs.map(&:name)
|
|
||||||
dependencies.any? {|d| !spec_names.include? d.name }
|
|
||||||
end
|
|
||||||
|
|
||||||
# Represents only the non-development dependencies, the ones that are
|
# Represents only the non-development dependencies, the ones that are
|
||||||
# itself and are in the total list.
|
# itself and are in the total list.
|
||||||
def dependencies
|
def dependencies
|
||||||
@ -123,11 +116,7 @@ module Bundler
|
|||||||
unmet_dependencies.each do |spec, unmet_spec_dependencies|
|
unmet_dependencies.each do |spec, unmet_spec_dependencies|
|
||||||
unmet_spec_dependencies.each do |unmet_spec_dependency|
|
unmet_spec_dependencies.each do |unmet_spec_dependency|
|
||||||
found = @specs.find {|s| s.name == unmet_spec_dependency.name && !unmet_spec_dependency.matches_spec?(s.spec) }
|
found = @specs.find {|s| s.name == unmet_spec_dependency.name && !unmet_spec_dependency.matches_spec?(s.spec) }
|
||||||
if found
|
warning << "* #{unmet_spec_dependency}, dependency of #{spec.full_name}, unsatisfied by #{found.full_name}"
|
||||||
warning << "* #{unmet_spec_dependency}, dependency of #{spec.full_name}, unsatisfied by #{found.full_name}"
|
|
||||||
else
|
|
||||||
warning << "* #{unmet_spec_dependency}, dependency of #{spec.full_name} but missing from lockfile"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -224,8 +213,6 @@ module Bundler
|
|||||||
if spec.dependencies_installed? @specs
|
if spec.dependencies_installed? @specs
|
||||||
spec.state = :enqueued
|
spec.state = :enqueued
|
||||||
worker_pool.enq spec
|
worker_pool.enq spec
|
||||||
elsif spec.dependencies_missing? @specs
|
|
||||||
spec.state = :failed
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -24,6 +24,7 @@ module Bundler
|
|||||||
|
|
||||||
name = dep[0].name
|
name = dep[0].name
|
||||||
platform = dep[1]
|
platform = dep[1]
|
||||||
|
incomplete = false
|
||||||
|
|
||||||
key = [name, platform]
|
key = [name, platform]
|
||||||
next if handled.key?(key)
|
next if handled.key?(key)
|
||||||
@ -36,11 +37,14 @@ module Bundler
|
|||||||
|
|
||||||
specs_for_dep.first.dependencies.each do |d|
|
specs_for_dep.first.dependencies.each do |d|
|
||||||
next if d.type == :development
|
next if d.type == :development
|
||||||
|
incomplete = true if d.name != "bundler" && lookup[d.name].empty?
|
||||||
deps << [d, dep[1]]
|
deps << [d, dep[1]]
|
||||||
end
|
end
|
||||||
elsif check
|
else
|
||||||
@incomplete_specs += lookup[name]
|
incomplete = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@incomplete_specs += lookup[name] if incomplete && check
|
||||||
end
|
end
|
||||||
|
|
||||||
specs
|
specs
|
||||||
|
@ -1221,7 +1221,7 @@ RSpec.describe "the lockfile format" do
|
|||||||
and include("Either installing with `--full-index` or running `bundle update rack_middleware` should fix the problem.")
|
and include("Either installing with `--full-index` or running `bundle update rack_middleware` should fix the problem.")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "errors gracefully on a corrupt lockfile" do
|
it "auto-heals when the lockfile is missing dependent specs" do
|
||||||
build_repo4 do
|
build_repo4 do
|
||||||
build_gem "minitest-bisect", "1.6.0" do |s|
|
build_gem "minitest-bisect", "1.6.0" do |s|
|
||||||
s.add_dependency "path_expander", "~> 1.1"
|
s.add_dependency "path_expander", "~> 1.1"
|
||||||
@ -1253,10 +1253,25 @@ RSpec.describe "the lockfile format" do
|
|||||||
L
|
L
|
||||||
|
|
||||||
cache_gems "minitest-bisect-1.6.0", "path_expander-1.1.1", :gem_repo => gem_repo4
|
cache_gems "minitest-bisect-1.6.0", "path_expander-1.1.1", :gem_repo => gem_repo4
|
||||||
bundle :install, :raise_on_error => false
|
bundle :install
|
||||||
|
|
||||||
expect(err).not_to include("ERROR REPORT TEMPLATE")
|
expect(lockfile).to eq <<~L
|
||||||
expect(err).to include("path_expander (~> 1.1), dependency of minitest-bisect-1.6.0 but missing from lockfile")
|
GEM
|
||||||
|
remote: #{file_uri_for(gem_repo4)}/
|
||||||
|
specs:
|
||||||
|
minitest-bisect (1.6.0)
|
||||||
|
path_expander (~> 1.1)
|
||||||
|
path_expander (1.1.1)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
#{lockfile_platforms}
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
minitest-bisect
|
||||||
|
|
||||||
|
BUNDLED WITH
|
||||||
|
#{Bundler::VERSION}
|
||||||
|
L
|
||||||
end
|
end
|
||||||
|
|
||||||
it "auto-heals when the lockfile is missing specs" do
|
it "auto-heals when the lockfile is missing specs" do
|
||||||
|
Loading…
x
Reference in New Issue
Block a user