diff options
author | David RodrÃguez <deivid.rodriguez@riseup.net> | 2022-12-15 12:14:40 +0100 |
---|---|---|
committer | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2022-12-20 13:15:02 +0900 |
commit | 3fd33590f624ff74d91c1d505f85653902764384 (patch) | |
tree | f978c5711f41681ff49d86b79e2c9089ab4309f5 | |
parent | 16b36a5b0c71afdcd125c530ee6fb809d4306822 (diff) |
[rubygems/rubygems] Fix crash when lockfile is missing dependencies
We have a check for a corrupt lockfile right before installing. However,
the check accounted for locked specs not satisfying locked dependencies,
but not for locked specs missing for some locked dependencies.
Instead of fixing this check, I decided to remove it in favor of
automatically detecting the situation and re-resolve to automatically
fix the lockfile rather than printing a warning but leave the problem
there.
https://github.com/rubygems/rubygems/commit/4a7a584252
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/6966
-rw-r--r-- | lib/bundler/definition.rb | 13 | ||||
-rw-r--r-- | lib/bundler/installer/parallel_installer.rb | 31 | ||||
-rw-r--r-- | spec/bundler/bundler/installer/parallel_installer_spec.rb | 34 | ||||
-rw-r--r-- | spec/bundler/lock/lockfile_spec.rb | 53 |
4 files changed, 65 insertions, 66 deletions
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 08f6c37de9..8659c64849 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -144,6 +144,8 @@ module Bundler @dependency_changes = converge_dependencies @local_changes = converge_locals + + @incomplete_lockfile = check_missing_lockfile_specs end def gem_version_promoter @@ -458,7 +460,7 @@ module Bundler private :sources def nothing_changed? - !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes + !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@incomplete_lockfile end def unlocking? @@ -603,6 +605,7 @@ module Bundler [@new_platform, "you added a new platform to your gemfile"], [@path_changes, "the gemspecs for path gems changed"], [@local_changes, "the gemspecs for git local gems changed"], + [@incomplete_lockfile, "your lock file is missing some gems"], ].select(&:first).map(&:last).join(", ") end @@ -657,6 +660,14 @@ module Bundler !sources_with_changes.each {|source| @unlock[:sources] << source.name }.empty? end + def check_missing_lockfile_specs + all_locked_specs = @locked_specs.map(&:name) << "bundler" + + @locked_specs.any? do |s| + s.dependencies.any? {|dep| !all_locked_specs.include?(dep.name) } + end + end + def converge_paths sources.path_sources.any? do |source| specs_changed?(source) diff --git a/lib/bundler/installer/parallel_installer.rb b/lib/bundler/installer/parallel_installer.rb index 5b6680e5e1..dce7133769 100644 --- a/lib/bundler/installer/parallel_installer.rb +++ b/lib/bundler/installer/parallel_installer.rb @@ -53,10 +53,6 @@ module Bundler @dependencies ||= all_dependencies.reject {|dep| ignorable_dependency? dep } end - def missing_lockfile_dependencies(all_spec_names) - dependencies.reject {|dep| all_spec_names.include? dep.name } - end - # Represents all dependencies def all_dependencies @spec.dependencies @@ -84,8 +80,6 @@ module Bundler end def call - check_for_corrupt_lockfile - if @rake do_install(@rake, 0) Gem::Specification.reset @@ -128,31 +122,6 @@ module Bundler Bundler.ui.warn(warning.join("\n")) end - def check_for_corrupt_lockfile - missing_dependencies = @specs.map do |s| - [ - s, - s.missing_lockfile_dependencies(@specs.map(&:name)), - ] - end.reject {|a| a.last.empty? } - return if missing_dependencies.empty? - - warning = [] - warning << "Your lockfile was created by an old Bundler that left some things out." - if @size != 1 - warning << "Because of the missing DEPENDENCIES, we can only install gems one at a time, instead of installing #{@size} at a time." - @size = 1 - end - warning << "You can fix this by adding the missing gems to your Gemfile, running bundle install, and then removing the gems from your Gemfile." - warning << "The missing gems are:" - - missing_dependencies.each do |spec, missing| - warning << "* #{missing.map(&:name).join(", ")} depended upon by #{spec.name}" - end - - Bundler.ui.warn(warning.join("\n")) - end - private def failed_specs diff --git a/spec/bundler/bundler/installer/parallel_installer_spec.rb b/spec/bundler/bundler/installer/parallel_installer_spec.rb index e680633862..f67d03356d 100644 --- a/spec/bundler/bundler/installer/parallel_installer_spec.rb +++ b/spec/bundler/bundler/installer/parallel_installer_spec.rb @@ -11,40 +11,6 @@ RSpec.describe Bundler::ParallelInstaller do subject { described_class.new(installer, all_specs, size, standalone, force) } - context "when dependencies that are not on the overall installation list are the only ones not installed" do - let(:all_specs) do - [ - build_spec("alpha", "1.0") {|s| s.runtime "a", "1" }, - ].flatten - end - - it "prints a warning" do - expect(Bundler.ui).to receive(:warn).with(<<-W.strip) -Your lockfile was created by an old Bundler that left some things out. -You can fix this by adding the missing gems to your Gemfile, running bundle install, and then removing the gems from your Gemfile. -The missing gems are: -* a depended upon by alpha - W - subject.check_for_corrupt_lockfile - end - - context "when size > 1" do - let(:size) { 500 } - - it "prints a warning and sets size to 1" do - expect(Bundler.ui).to receive(:warn).with(<<-W.strip) -Your lockfile was created by an old Bundler that left some things out. -Because of the missing DEPENDENCIES, we can only install gems one at a time, instead of installing 500 at a time. -You can fix this by adding the missing gems to your Gemfile, running bundle install, and then removing the gems from your Gemfile. -The missing gems are: -* a depended upon by alpha - W - subject.check_for_corrupt_lockfile - expect(subject.size).to eq(1) - end - end - end - context "when the spec set is not a valid resolution" do let(:all_specs) do [ diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb index 29f8863591..cd603e336a 100644 --- a/spec/bundler/lock/lockfile_spec.rb +++ b/spec/bundler/lock/lockfile_spec.rb @@ -1221,6 +1221,59 @@ RSpec.describe "the lockfile format" do and include("Either installing with `--full-index` or running `bundle update rack_middleware` should fix the problem.") end + it "auto-heals when the lockfile is missing specs" do + build_repo4 do + build_gem "minitest-bisect", "1.6.0" do |s| + s.add_dependency "path_expander", "~> 1.1" + end + + build_gem "path_expander", "1.1.1" + end + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + gem "minitest-bisect" + G + + lockfile <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + minitest-bisect (1.6.0) + path_expander (~> 1.1) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + minitest-bisect + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "install --verbose" + expect(out).to include("re-resolving dependencies because your lock file is missing some gems") + + expect(lockfile).to eq <<~L + 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 + describe "a line ending" do def set_lockfile_mtime_to_known_value time = Time.local(2000, 1, 1, 0, 0, 0) |