diff options
Diffstat (limited to 'spec/bundler/lock/lockfile_spec.rb')
-rw-r--r-- | spec/bundler/lock/lockfile_spec.rb | 809 |
1 files changed, 576 insertions, 233 deletions
diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb index 9170efeedd..4fd081e7d0 100644 --- a/spec/bundler/lock/lockfile_spec.rb +++ b/spec/bundler/lock/lockfile_spec.rb @@ -1,28 +1,22 @@ # frozen_string_literal: true RSpec.describe "the lockfile format" do - include Bundler::GemHelpers - before do - build_repo2 do - # Capistrano did this (at least until version 2.5.10) - # RubyGems 2.2 doesn't allow the specifying of a dependency twice - # See https://github.com/rubygems/rubygems/commit/03dbac93a3396a80db258d9bc63500333c25bd2f - build_gem "double_deps", "1.0", :skip_validation => true do |s| - s.add_dependency "net-ssh", ">= 1.0.0" - s.add_dependency "net-ssh" - end - end + build_repo2 end it "generates a simple lockfile for a single source, gem" do + checksums = checksums_section_when_existing do |c| + c.checksum(gem_repo2, "rack", "1.0.0") + end + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" gem "rack" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -33,13 +27,13 @@ RSpec.describe "the lockfile format" do DEPENDENCIES rack - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G end - it "updates the lockfile's bundler version if current ver. is newer" do + it "updates the lockfile's bundler version if current ver. is newer, and version was forced through BUNDLER_VERSION" do system_gems "bundler-1.8.2" lockfile <<-L @@ -64,13 +58,16 @@ RSpec.describe "the lockfile format" do 1.8.2 L - install_gemfile <<-G, :env => { "BUNDLER_VERSION" => Bundler::VERSION } + install_gemfile <<-G, verbose: true, env: { "BUNDLER_VERSION" => Bundler::VERSION } source "#{file_uri_for(gem_repo2)}" gem "rack" G - lockfile_should_be <<-G + expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with 1.8.2.") + expect(out).to include("Using bundler #{Bundler::VERSION}") + + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -87,8 +84,8 @@ RSpec.describe "the lockfile format" do G end - it "does not update the lockfile's bundler version if nothing changed during bundle install" do - version = "#{Bundler::VERSION.split(".").first}.0.0.a" + it "does not update the lockfile's bundler version if nothing changed during bundle install, but uses the locked version", rubygems: ">= 3.3.0.a", realworld: true do + version = "2.3.0" lockfile <<-L GEM @@ -106,31 +103,16 @@ RSpec.describe "the lockfile format" do #{version} L - install_gemfile <<-G + install_gemfile <<-G, verbose: true, artifice: "vcr" source "#{file_uri_for(gem_repo2)}" gem "rack" G - lockfile_should_be <<-G - GEM - remote: #{file_uri_for(gem_repo2)}/ - specs: - rack (1.0.0) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - rack + expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{version}.") + expect(out).to include("Using bundler #{version}") - BUNDLED WITH - #{version} - G - end - - it "updates the lockfile's bundler version if not present" do - lockfile <<-L + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -141,85 +123,18 @@ RSpec.describe "the lockfile format" do DEPENDENCIES rack - L - - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - - gem "rack", "> 0" - G - - lockfile_should_be <<-G - GEM - remote: #{file_uri_for(gem_repo2)}/ - specs: - rack (1.0.0) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - rack (> 0) BUNDLED WITH - #{Bundler::VERSION} + #{version} G end - it "warns if the current version is older than lockfile's bundler version, and locked version is a final release" do - current_version = "999.998.999" - system_gems "bundler-#{current_version}" - newer_minor = "999.999.0" - - lockfile <<-L - GEM - remote: #{file_uri_for(gem_repo2)}/ - specs: - rack (1.0.0) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - rack - - BUNDLED WITH - #{newer_minor} - L - - install_gemfile <<-G, :env => { "BUNDLER_VERSION" => current_version } - source "#{file_uri_for(gem_repo2)}" - - gem "rack" - G - - warning_message = "the running version of Bundler (#{current_version}) is older " \ - "than the version that created the lockfile (#{newer_minor}). " \ - "We suggest you to upgrade to the version that created the " \ - "lockfile by running `gem install bundler:#{newer_minor}`." - expect(err).to include warning_message - - lockfile_should_be <<-G - GEM - remote: #{file_uri_for(gem_repo2)}/ - specs: - rack (1.0.0) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - rack - - BUNDLED WITH - #{newer_minor} - G - end + it "does not update the lockfile's bundler version if nothing changed during bundle install, and uses the latest version", rubygems: "< 3.3.0.a" do + version = "#{Bundler::VERSION.split(".").first}.0.0.a" - it "warns if the current version is older than lockfile's bundler version, and locked version is a prerelease" do - current_version = "999.998.999" - system_gems "bundler-#{current_version}" - newer_minor = "999.999.0.pre1" + checksums = checksums_section do |c| + c.checksum(gem_repo2, "rack", "1.0.0") + end lockfile <<-L GEM @@ -232,24 +147,21 @@ RSpec.describe "the lockfile format" do DEPENDENCIES rack - + #{checksums} BUNDLED WITH - #{newer_minor} + #{version} L - install_gemfile <<-G, :env => { "BUNDLER_VERSION" => current_version } + install_gemfile <<-G, verbose: true source "#{file_uri_for(gem_repo2)}" gem "rack" G - warning_message = "the running version of Bundler (#{current_version}) is older " \ - "than the version that created the lockfile (#{newer_minor}). " \ - "We suggest you to upgrade to the version that created the " \ - "lockfile by running `gem install bundler:#{newer_minor} --pre`." - expect(err).to include warning_message + expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{version}.") + expect(out).to include("Using bundler #{Bundler::VERSION}") - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -260,17 +172,13 @@ RSpec.describe "the lockfile format" do DEPENDENCIES rack - + #{checksums} BUNDLED WITH - #{newer_minor} + #{version} G end - it "doesn't warn if the current version is older than lockfile's bundler version, and locked version is a dev version" do - current_version = "999.998.999" - system_gems "bundler-#{current_version}" - newer_minor = "999.999.0.dev" - + it "adds the BUNDLED WITH section if not present" do lockfile <<-L GEM remote: #{file_uri_for(gem_repo2)}/ @@ -282,20 +190,15 @@ RSpec.describe "the lockfile format" do DEPENDENCIES rack - - BUNDLED WITH - #{newer_minor} L - install_gemfile <<-G, :env => { "BUNDLER_VERSION" => current_version } + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" - gem "rack" + gem "rack", "> 0" G - expect(err).to be_empty - - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -305,14 +208,14 @@ RSpec.describe "the lockfile format" do #{lockfile_platforms} DEPENDENCIES - rack + rack (> 0) BUNDLED WITH - #{newer_minor} + #{Bundler::VERSION} G end - it "warns when updating bundler major version" do + it "update the bundler major version just fine" do current_version = Bundler::VERSION older_major = previous_major(current_version) @@ -334,18 +237,15 @@ RSpec.describe "the lockfile format" do #{older_major} L - install_gemfile <<-G, :env => { "BUNDLER_VERSION" => Bundler::VERSION } + install_gemfile <<-G, env: { "BUNDLER_VERSION" => Bundler::VERSION } source "#{file_uri_for(gem_repo2)}/" gem "rack" G - expect(err).to include( - "Warning: the lockfile is being updated to Bundler " \ - "#{current_version.split(".").first}, after which you will be unable to return to Bundler #{older_major.split(".").first}." - ) + expect(err).to be_empty - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -369,7 +269,12 @@ RSpec.describe "the lockfile format" do gem "rack-obama" G - lockfile_should_be <<-G + checksums = checksums_section_when_existing do |c| + c.checksum gem_repo2, "rack", "1.0.0" + c.checksum gem_repo2, "rack-obama", "1.0" + end + + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -382,7 +287,7 @@ RSpec.describe "the lockfile format" do DEPENDENCIES rack-obama - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G @@ -395,7 +300,12 @@ RSpec.describe "the lockfile format" do gem "rack-obama", ">= 1.0" G - lockfile_should_be <<-G + checksums = checksums_section_when_existing do |c| + c.checksum gem_repo2, "rack", "1.0.0" + c.checksum gem_repo2, "rack-obama", "1.0" + end + + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -408,16 +318,16 @@ RSpec.describe "the lockfile format" do DEPENDENCIES rack-obama (>= 1.0) - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G end - it "generates a lockfile without credentials for a configured source" do + it "generates a lockfile without credentials" do bundle "config set http://localgemserver.test/ user:pass" - install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true) + install_gemfile(<<-G, artifice: "endpoint_strict_basic_authentication", quiet: true) source "#{file_uri_for(gem_repo1)}" source "http://localgemserver.test/" do @@ -429,7 +339,12 @@ RSpec.describe "the lockfile format" do end G - lockfile_should_be <<-G + checksums = checksums_section_when_existing do |c| + c.checksum gem_repo2, "rack", "1.0.0" + c.checksum gem_repo2, "rack-obama", "1.0" + end + + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo1)}/ specs: @@ -439,7 +354,7 @@ RSpec.describe "the lockfile format" do specs: GEM - remote: http://user:pass@othergemserver.test/ + remote: http://othergemserver.test/ specs: rack (1.0.0) rack-obama (1.0) @@ -450,7 +365,7 @@ RSpec.describe "the lockfile format" do DEPENDENCIES rack-obama (>= 1.0)! - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G @@ -462,7 +377,12 @@ RSpec.describe "the lockfile format" do gem "net-sftp" G - lockfile_should_be <<-G + checksums = checksums_section_when_existing do |c| + c.checksum gem_repo2, "net-sftp", "1.1.1" + c.checksum gem_repo2, "net-ssh", "1.0" + end + + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -475,7 +395,7 @@ RSpec.describe "the lockfile format" do DEPENDENCIES net-sftp - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G @@ -491,10 +411,14 @@ RSpec.describe "the lockfile format" do gem "foo", :git => "#{lib_path("foo-1.0")}" G - lockfile_should_be <<-G + checksums = checksums_section_when_existing do |c| + c.no_checksum "foo", "1.0" + end + + expect(lockfile).to eq <<~G GIT remote: #{lib_path("foo-1.0")} - revision: #{git.ref_for("master")} + revision: #{git.ref_for("main")} specs: foo (1.0) @@ -507,14 +431,14 @@ RSpec.describe "the lockfile format" do DEPENDENCIES foo! - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G end it "does not asplode when a platform specific dependency is present and the Gemfile has not been resolved on that platform" do - build_lib "omg", :path => lib_path("omg") + build_lib "omg", path: lib_path("omg") gemfile <<-G source "#{file_uri_for(gem_repo2)}/" @@ -555,6 +479,10 @@ RSpec.describe "the lockfile format" do it "serializes global git sources" do git = build_git "foo" + checksums = checksums_section_when_existing do |c| + c.no_checksum "foo", "1.0" + end + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" git "#{lib_path("foo-1.0")}" do @@ -562,10 +490,10 @@ RSpec.describe "the lockfile format" do end G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GIT remote: #{lib_path("foo-1.0")} - revision: #{git.ref_for("master")} + revision: #{git.ref_for("main")} specs: foo (1.0) @@ -578,7 +506,7 @@ RSpec.describe "the lockfile format" do DEPENDENCIES foo! - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G @@ -586,14 +514,18 @@ RSpec.describe "the lockfile format" do it "generates a lockfile with a ref for a single pinned source, git gem with a branch requirement" do git = build_git "foo" - update_git "foo", :branch => "omg" + update_git "foo", branch: "omg" + + checksums = checksums_section_when_existing do |c| + c.no_checksum "foo", "1.0" + end install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "omg" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GIT remote: #{lib_path("foo-1.0")} revision: #{git.ref_for("omg")} @@ -610,7 +542,7 @@ RSpec.describe "the lockfile format" do DEPENDENCIES foo! - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G @@ -618,14 +550,18 @@ RSpec.describe "the lockfile format" do it "generates a lockfile with a ref for a single pinned source, git gem with a tag requirement" do git = build_git "foo" - update_git "foo", :tag => "omg" + update_git "foo", tag: "omg" + + checksums = checksums_section_when_existing do |c| + c.no_checksum "foo", "1.0" + end install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "foo", :git => "#{lib_path("foo-1.0")}", :tag => "omg" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GIT remote: #{lib_path("foo-1.0")} revision: #{git.ref_for("omg")} @@ -642,21 +578,111 @@ RSpec.describe "the lockfile format" do DEPENDENCIES foo! - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G end + it "is conservative with dependencies of git gems" do + build_repo4 do + build_gem "orm_adapter", "0.4.1" + build_gem "orm_adapter", "0.5.0" + end + + FileUtils.mkdir_p lib_path("ckeditor/lib") + + @remote = build_git("ckeditor_remote", bare: true) + + build_git "ckeditor", path: lib_path("ckeditor") do |s| + s.write "lib/ckeditor.rb", "CKEDITOR = '4.0.7'" + s.version = "4.0.7" + s.add_dependency "orm_adapter" + end + + update_git "ckeditor", path: lib_path("ckeditor"), remote: file_uri_for(@remote.path) + update_git "ckeditor", path: lib_path("ckeditor"), tag: "v4.0.7" + old_git = update_git "ckeditor", path: lib_path("ckeditor"), push: "v4.0.7" + + update_git "ckeditor", path: lib_path("ckeditor"), gemspec: true do |s| + s.write "lib/ckeditor.rb", "CKEDITOR = '4.0.8'" + s.version = "4.0.8" + s.add_dependency "orm_adapter" + end + update_git "ckeditor", path: lib_path("ckeditor"), tag: "v4.0.8" + + new_git = update_git "ckeditor", path: lib_path("ckeditor"), push: "v4.0.8" + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "ckeditor", :git => "#{@remote.path}", :tag => "v4.0.8" + G + + lockfile <<~L + GIT + remote: #{@remote.path} + revision: #{old_git.ref_for("v4.0.7")} + tag: v4.0.7 + specs: + ckeditor (4.0.7) + orm_adapter + + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + orm_adapter (0.4.1) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + ckeditor! + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "lock" + + # Bumps the git gem, but keeps its dependency locked + expect(lockfile).to eq <<~L + GIT + remote: #{@remote.path} + revision: #{new_git.ref_for("v4.0.8")} + tag: v4.0.8 + specs: + ckeditor (4.0.8) + orm_adapter + + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + orm_adapter (0.4.1) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + ckeditor! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + it "serializes pinned path sources to the lockfile" do build_lib "foo" + checksums = checksums_section_when_existing do |c| + c.no_checksum "foo", "1.0" + end + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "foo", :path => "#{lib_path("foo-1.0")}" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PATH remote: #{lib_path("foo-1.0")} specs: @@ -671,7 +697,7 @@ RSpec.describe "the lockfile format" do DEPENDENCIES foo! - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G @@ -680,6 +706,10 @@ RSpec.describe "the lockfile format" do it "serializes pinned path sources to the lockfile even when packaging" do build_lib "foo" + checksums = checksums_section_when_existing do |c| + c.no_checksum "foo", "1.0" + end + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "foo", :path => "#{lib_path("foo-1.0")}" @@ -687,9 +717,9 @@ RSpec.describe "the lockfile format" do bundle "config set cache_all true" bundle :cache - bundle :install, :local => true + bundle :install, local: true - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PATH remote: #{lib_path("foo-1.0")} specs: @@ -704,7 +734,7 @@ RSpec.describe "the lockfile format" do DEPENDENCIES foo! - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G @@ -714,6 +744,12 @@ RSpec.describe "the lockfile format" do build_lib "foo" bar = build_git "bar" + checksums = checksums_section_when_existing do |c| + c.no_checksum "foo", "1.0" + c.no_checksum "bar", "1.0" + c.checksum gem_repo2, "rack", "1.0.0" + end + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}/" @@ -722,10 +758,10 @@ RSpec.describe "the lockfile format" do gem "bar", :git => "#{lib_path("bar-1.0")}" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GIT remote: #{lib_path("bar-1.0")} - revision: #{bar.ref_for("master")} + revision: #{bar.ref_for("main")} specs: bar (1.0) @@ -746,7 +782,7 @@ RSpec.describe "the lockfile format" do bar! foo! rack - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G @@ -759,7 +795,11 @@ RSpec.describe "the lockfile format" do gem "rack", :source => "#{file_uri_for(gem_repo2)}/" G - lockfile_should_be <<-G + checksums = checksums_section_when_existing do |c| + c.checksum gem_repo2, "rack", "1.0.0" + end + + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -770,7 +810,7 @@ RSpec.describe "the lockfile format" do DEPENDENCIES rack! - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G @@ -785,7 +825,15 @@ RSpec.describe "the lockfile format" do gem "rack-obama" G - lockfile_should_be <<-G + checksums = checksums_section_when_existing do |c| + c.checksum gem_repo2, "actionpack", "2.3.2" + c.checksum gem_repo2, "activesupport", "2.3.2" + c.checksum gem_repo2, "rack", "1.0.0" + c.checksum gem_repo2, "rack-obama", "1.0" + c.checksum gem_repo2, "thin", "1.0" + end + + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -805,7 +853,7 @@ RSpec.describe "the lockfile format" do actionpack rack-obama thin - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G @@ -818,7 +866,17 @@ RSpec.describe "the lockfile format" do gem "rails" G - lockfile_should_be <<-G + checksums = checksums_section_when_existing do |c| + c.checksum gem_repo2, "actionmailer", "2.3.2" + c.checksum gem_repo2, "actionpack", "2.3.2" + c.checksum gem_repo2, "activerecord", "2.3.2" + c.checksum gem_repo2, "activeresource", "2.3.2" + c.checksum gem_repo2, "activesupport", "2.3.2" + c.checksum gem_repo2, "rails", "2.3.2" + c.checksum gem_repo2, "rake", rake_version + end + + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -836,27 +894,42 @@ RSpec.describe "the lockfile format" do actionpack (= 2.3.2) activerecord (= 2.3.2) activeresource (= 2.3.2) - rake (= 13.0.1) - rake (13.0.1) + rake (= #{rake_version}) + rake (#{rake_version}) PLATFORMS #{lockfile_platforms} DEPENDENCIES rails - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G end it "orders dependencies by version" do + update_repo2 do + # Capistrano did this (at least until version 2.5.10) + # RubyGems 2.2 doesn't allow the specifying of a dependency twice + # See https://github.com/rubygems/rubygems/commit/03dbac93a3396a80db258d9bc63500333c25bd2f + build_gem "double_deps", "1.0", skip_validation: true do |s| + s.add_dependency "net-ssh", ">= 1.0.0" + s.add_dependency "net-ssh" + end + end + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}/" gem 'double_deps' G - lockfile_should_be <<-G + checksums = checksums_section_when_existing do |c| + c.checksum gem_repo2, "double_deps", "1.0" + c.checksum gem_repo2, "net-ssh", "1.0" + end + + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -870,7 +943,7 @@ RSpec.describe "the lockfile format" do DEPENDENCIES double_deps - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G @@ -883,7 +956,12 @@ RSpec.describe "the lockfile format" do gem "rack-obama", ">= 1.0", :require => "rack/obama" G - lockfile_should_be <<-G + checksums = checksums_section_when_existing do |c| + c.checksum gem_repo2, "rack", "1.0.0" + c.checksum gem_repo2, "rack-obama", "1.0" + end + + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -896,7 +974,7 @@ RSpec.describe "the lockfile format" do DEPENDENCIES rack-obama (>= 1.0) - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G @@ -909,7 +987,12 @@ RSpec.describe "the lockfile format" do gem "rack-obama", ">= 1.0", :group => :test G - lockfile_should_be <<-G + checksums = checksums_section_when_existing do |c| + c.checksum gem_repo2, "rack", "1.0.0" + c.checksum gem_repo2, "rack-obama", "1.0" + end + + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -922,14 +1005,18 @@ RSpec.describe "the lockfile format" do DEPENDENCIES rack-obama (>= 1.0) - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G end it "stores relative paths when the path is provided in a relative fashion and in Gemfile dir" do - build_lib "foo", :path => bundled_app("foo") + build_lib "foo", path: bundled_app("foo") + + checksums = checksums_section_when_existing do |c| + c.no_checksum "foo", "1.0" + end install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -938,7 +1025,7 @@ RSpec.describe "the lockfile format" do end G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PATH remote: foo specs: @@ -953,14 +1040,18 @@ RSpec.describe "the lockfile format" do DEPENDENCIES foo! - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G end it "stores relative paths when the path is provided in a relative fashion and is above Gemfile dir" do - build_lib "foo", :path => bundled_app(File.join("..", "foo")) + build_lib "foo", path: bundled_app(File.join("..", "foo")) + + checksums = checksums_section_when_existing do |c| + c.no_checksum "foo", "1.0" + end install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -969,7 +1060,7 @@ RSpec.describe "the lockfile format" do end G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PATH remote: ../foo specs: @@ -984,23 +1075,27 @@ RSpec.describe "the lockfile format" do DEPENDENCIES foo! - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G end it "stores relative paths when the path is provided in an absolute fashion but is relative" do - build_lib "foo", :path => bundled_app("foo") + build_lib "foo", path: bundled_app("foo") + + checksums = checksums_section_when_existing do |c| + c.no_checksum "foo", "1.0" + end install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" - path File.expand_path("../foo", __FILE__) do + path File.expand_path("foo", __dir__) do gem "foo" end G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PATH remote: foo specs: @@ -1015,21 +1110,25 @@ RSpec.describe "the lockfile format" do DEPENDENCIES foo! - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G end it "stores relative paths when the path is provided for gemspec" do - build_lib("foo", :path => tmp.join("foo")) + build_lib("foo", path: tmp.join("foo")) + + checksums = checksums_section_when_existing do |c| + c.no_checksum "foo", "1.0" + end install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gemspec :path => "../foo" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G PATH remote: ../foo specs: @@ -1044,13 +1143,17 @@ RSpec.describe "the lockfile format" do DEPENDENCIES foo! - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G end it "keeps existing platforms in the lockfile" do + checksums = checksums_section_when_existing do |c| + c.no_checksum "rack", "1.0.0" + end + lockfile <<-G GEM remote: #{file_uri_for(gem_repo2)}/ @@ -1062,7 +1165,7 @@ RSpec.describe "the lockfile format" do DEPENDENCIES rack - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G @@ -1073,23 +1176,65 @@ RSpec.describe "the lockfile format" do gem "rack" G - lockfile_should_be <<-G + checksums.checksum(gem_repo2, "rack", "1.0.0") + + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: rack (1.0.0) PLATFORMS - #{lockfile_platforms_for(["java"] + local_platforms)} + #{lockfile_platforms("java", local_platform, defaults: [])} DEPENDENCIES rack - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G end + it "adds compatible platform specific variants to the lockfile, even if resolution fallback to RUBY due to some other incompatible platform specific variant" do + simulate_platform "arm64-darwin-23" do + build_repo4 do + build_gem "google-protobuf", "3.25.1" + build_gem "google-protobuf", "3.25.1" do |s| + s.platform = "arm64-darwin-23" + end + build_gem "google-protobuf", "3.25.1" do |s| + s.platform = "x64-mingw-ucrt" + s.required_ruby_version = "> #{Gem.ruby_version}" + end + end + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "google-protobuf" + G + bundle "lock --add-platform x64-mingw-ucrt" + + expect(lockfile).to eq <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + google-protobuf (3.25.1) + google-protobuf (3.25.1-arm64-darwin-23) + + PLATFORMS + arm64-darwin-23 + ruby + x64-mingw-ucrt + + DEPENDENCIES + google-protobuf + + BUNDLED WITH + #{Bundler::VERSION} + L + end + end + it "persists the spec's specific platform to the lockfile" do build_repo2 do build_gem "platform_specific", "1.0" do |s| @@ -1104,7 +1249,11 @@ RSpec.describe "the lockfile format" do gem "platform_specific" G - lockfile_should_be <<-G + checksums = checksums_section_when_existing do |c| + c.checksum gem_repo2, "platform_specific", "1.0", "universal-java-16" + end + + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -1115,13 +1264,18 @@ RSpec.describe "the lockfile format" do DEPENDENCIES platform_specific - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G end it "does not add duplicate gems" do + checksums = checksums_section_when_existing do |c| + c.checksum(gem_repo2, "activesupport", "2.3.5") + c.checksum(gem_repo2, "rack", "1.0.0") + end + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}/" gem "rack" @@ -1133,7 +1287,7 @@ RSpec.describe "the lockfile format" do gem "activesupport" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -1146,20 +1300,24 @@ RSpec.describe "the lockfile format" do DEPENDENCIES activesupport rack - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G end it "does not add duplicate dependencies" do + checksums = checksums_section_when_existing do |c| + c.checksum(gem_repo2, "rack", "1.0.0") + end + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}/" gem "rack" gem "rack" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -1170,20 +1328,24 @@ RSpec.describe "the lockfile format" do DEPENDENCIES rack - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G end it "does not add duplicate dependencies with versions" do + checksums = checksums_section_when_existing do |c| + c.checksum(gem_repo2, "rack", "1.0.0") + end + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}/" gem "rack", "1.0" gem "rack", "1.0" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -1194,20 +1356,24 @@ RSpec.describe "the lockfile format" do DEPENDENCIES rack (= 1.0) - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G end it "does not add duplicate dependencies in different groups" do + checksums = checksums_section_when_existing do |c| + c.checksum(gem_repo2, "rack", "1.0.0") + end + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}/" gem "rack", "1.0", :group => :one gem "rack", "1.0", :group => :two G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -1218,14 +1384,14 @@ RSpec.describe "the lockfile format" do DEPENDENCIES rack (= 1.0) - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G end it "raises if two different versions are used" do - install_gemfile <<-G, :raise_on_error => false + install_gemfile <<-G, raise_on_error: false source "#{file_uri_for(gem_repo2)}/" gem "rack", "1.0" gem "rack", "1.1" @@ -1236,7 +1402,7 @@ RSpec.describe "the lockfile format" do end it "raises if two different sources are used" do - install_gemfile <<-G, :raise_on_error => false + install_gemfile <<-G, raise_on_error: false source "#{file_uri_for(gem_repo2)}/" gem "rack" gem "rack", :git => "git://hubz.com" @@ -1247,12 +1413,16 @@ RSpec.describe "the lockfile format" do end it "works correctly with multiple version dependencies" do + checksums = checksums_section_when_existing do |c| + c.checksum(gem_repo2, "rack", "0.9.1") + end + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}/" gem "rack", "> 0.9", "< 1.0" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -1263,20 +1433,24 @@ RSpec.describe "the lockfile format" do DEPENDENCIES rack (> 0.9, < 1.0) - + #{checksums} BUNDLED WITH #{Bundler::VERSION} G end it "captures the Ruby version in the lockfile" do + checksums = checksums_section_when_existing do |c| + c.checksum(gem_repo2, "rack", "0.9.1") + end + install_gemfile <<-G source "#{file_uri_for(gem_repo2)}/" - ruby '#{RUBY_VERSION}' + ruby '#{Gem.ruby_version}' gem "rack", "> 0.9", "< 1.0" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM remote: #{file_uri_for(gem_repo2)}/ specs: @@ -1287,9 +1461,9 @@ RSpec.describe "the lockfile format" do DEPENDENCIES rack (> 0.9, < 1.0) - + #{checksums} RUBY VERSION - ruby #{RUBY_VERSION}p#{RUBY_PATCHLEVEL} + #{Bundler::RubyVersion.system} BUNDLED WITH #{Bundler::VERSION} @@ -1310,13 +1484,184 @@ RSpec.describe "the lockfile format" do rack_middleware L - install_gemfile <<-G, :raise_on_error => false + install_gemfile <<-G, raise_on_error: false source "#{file_uri_for(gem_repo2)}" gem "rack_middleware" G expect(err).to include("Downloading rack_middleware-1.0 revealed dependencies not in the API or the lockfile (#{Gem::Dependency.new("rack", "= 0.9.1")})."). - and include("Either installing with `--full-index` or running `bundle update rack_middleware` should fix the problem.") + and include("Running `bundle update rack_middleware` should fix the problem.") + end + + it "regenerates a lockfile with no specs" do + build_repo4 do + build_gem "indirect_dependency", "1.2.3" do |s| + s.metadata["funding_uri"] = "https://example.com/donate" + end + + build_gem "direct_dependency", "4.5.6" do |s| + s.add_dependency "indirect_dependency", ">= 0" + end + end + + lockfile <<-G + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + + PLATFORMS + ruby + + DEPENDENCIES + direct_dependency + + BUNDLED WITH + #{Bundler::VERSION} + G + + install_gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + + gem "direct_dependency" + G + + expect(lockfile).to eq <<~G + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + direct_dependency (4.5.6) + indirect_dependency + indirect_dependency (1.2.3) + + PLATFORMS + #{lockfile_platforms("ruby", generic_local_platform, defaults: [])} + + DEPENDENCIES + direct_dependency + + BUNDLED WITH + #{Bundler::VERSION} + G + end + + shared_examples_for "a lockfile missing dependent specs" do + it "auto-heals" 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 + + # Corrupt lockfile (completely missing path_expander) + lockfile <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + minitest-bisect (1.6.0) + + PLATFORMS + #{platforms} + + DEPENDENCIES + minitest-bisect + + BUNDLED WITH + #{Bundler::VERSION} + L + + cache_gems "minitest-bisect-1.6.0", "path_expander-1.1.1", gem_repo: gem_repo4 + bundle :install + + 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 + #{platforms} + + DEPENDENCIES + minitest-bisect + + BUNDLED WITH + #{Bundler::VERSION} + L + end + end + + context "with just specific platform" do + let(:platforms) { lockfile_platforms } + + it_behaves_like "a lockfile missing dependent specs" + end + + context "with both ruby and specific platform" do + let(:platforms) { lockfile_platforms("ruby") } + + it_behaves_like "a lockfile missing dependent specs" + 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 includes \"minitest-bisect\" but not some of its dependencies") + + 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 @@ -1347,7 +1692,7 @@ RSpec.describe "the lockfile format" do end end - expect { bundle "update", :all => true }.to change { File.mtime(bundled_app_lock) } + expect { bundle "update", all: true }.to change { File.mtime(bundled_app_lock) } expect(File.read(bundled_app_lock)).not_to match("\r\n") expect(the_bundle).to include_gems "rack 1.2" end @@ -1365,12 +1710,10 @@ RSpec.describe "the lockfile format" do File.open(bundled_app_lock, "wb") {|f| f.puts(win_lock) } set_lockfile_mtime_to_known_value - expect { bundle "update", :all => true }.to change { File.mtime(bundled_app_lock) } + expect { bundle "update", all: true }.to change { File.mtime(bundled_app_lock) } expect(File.read(bundled_app_lock)).to match("\r\n") - simulate_bundler_version_when_missing_prerelease_default_gem_activation do - expect(the_bundle).to include_gems "rack 1.2" - end + expect(the_bundle).to include_gems "rack 1.2" end end @@ -1391,7 +1734,7 @@ RSpec.describe "the lockfile format" do expect do ruby <<-RUBY - require '#{entrypoint}' + require 'bundler' Bundler.setup RUBY end.not_to change { File.mtime(bundled_app_lock) } @@ -1420,7 +1763,7 @@ RSpec.describe "the lockfile format" do #{Bundler::VERSION} L - install_gemfile <<-G, :raise_on_error => false + install_gemfile <<-G, raise_on_error: false source "#{file_uri_for(gem_repo2)}/" gem "rack" G |