diff options
Diffstat (limited to 'spec/bundler/lock')
| -rw-r--r-- | spec/bundler/lock/git_spec.rb | 226 | ||||
| -rw-r--r-- | spec/bundler/lock/lockfile_bundler_1_spec.rb | 1386 | ||||
| -rw-r--r-- | spec/bundler/lock/lockfile_spec.rb | 2047 |
3 files changed, 1744 insertions, 1915 deletions
diff --git a/spec/bundler/lock/git_spec.rb b/spec/bundler/lock/git_spec.rb index 14b80483ee..c9f76115dc 100644 --- a/spec/bundler/lock/git_spec.rb +++ b/spec/bundler/lock/git_spec.rb @@ -1,19 +1,76 @@ # frozen_string_literal: true RSpec.describe "bundle lock with git gems" do - before :each do + let(:install_gemfile_with_foo_as_a_git_dependency) do build_git "foo" install_gemfile <<-G + source "https://gem.repo1" gem 'foo', :git => "#{lib_path("foo-1.0")}" G end it "doesn't break right after running lock" do + install_gemfile_with_foo_as_a_git_dependency + expect(the_bundle).to include_gems "foo 1.0.0" end + it "doesn't print errors even if running lock after removing the cache" do + install_gemfile_with_foo_as_a_git_dependency + + FileUtils.rm_r(Dir[default_cache_path("git/foo-1.0-*")].first) + + bundle "lock --verbose" + + expect(err).to be_empty + end + + it "prints a proper error when changing a locked Gemfile to point to a bad branch" do + install_gemfile_with_foo_as_a_git_dependency + + gemfile <<-G + source "https://gem.repo1" + gem 'foo', :git => "#{lib_path("foo-1.0")}", :branch => "bad" + G + + bundle "lock --update foo", env: { "LANG" => "en" }, raise_on_error: false + + expect(err).to include("Revision bad does not exist in the repository") + end + + it "prints a proper error when installing a Gemfile with a locked ref that does not exist" do + install_gemfile_with_foo_as_a_git_dependency + + lockfile <<~L + GIT + remote: #{lib_path("foo-1.0")} + revision: #{"a" * 40} + specs: + foo (1.0) + + GEM + remote: https://gem.repo1/ + specs: + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + foo! + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "install", raise_on_error: false + + expect(err).to include("Revision #{"a" * 40} does not exist in the repository") + end + it "locks a git source to the current ref" do + install_gemfile_with_foo_as_a_git_dependency + update_git "foo" bundle :install @@ -25,10 +82,177 @@ RSpec.describe "bundle lock with git gems" do expect(out).to eq("WIN") end + it "properly clones a git source locked to an out of date ref" do + install_gemfile_with_foo_as_a_git_dependency + + update_git "foo" + + bundle :install, env: { "BUNDLE_PATH" => "foo" } + expect(err).to be_empty + end + + it "properly fetches a git source locked to an unreachable ref" do + install_gemfile_with_foo_as_a_git_dependency + + # Create a commit and make it unreachable + git "checkout -b foo ", lib_path("foo-1.0") + unreachable_sha = update_git("foo").ref_for("HEAD") + git "checkout main ", lib_path("foo-1.0") + git "branch -D foo ", lib_path("foo-1.0") + + gemfile <<-G + source "https://gem.repo1" + gem 'foo', :git => "#{lib_path("foo-1.0")}" + G + + lockfile <<-L + GIT + remote: #{lib_path("foo-1.0")} + revision: #{unreachable_sha} + specs: + foo (1.0) + + GEM + remote: https://gem.repo1/ + specs: + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + foo! + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "install" + + expect(err).to be_empty + end + + it "properly fetches a git source locked to an annotated tag" do + install_gemfile_with_foo_as_a_git_dependency + + # Create an annotated tag + git("tag -a v1.0 -m 'Annotated v1.0'", lib_path("foo-1.0")) + annotated_tag = git("rev-parse v1.0", lib_path("foo-1.0")) + + gemfile <<-G + source "https://gem.repo1" + gem 'foo', :git => "#{lib_path("foo-1.0")}" + G + + lockfile <<-L + GIT + remote: #{lib_path("foo-1.0")} + revision: #{annotated_tag} + specs: + foo (1.0) + + GEM + remote: https://gem.repo1/ + specs: + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + foo! + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "install" + + expect(err).to be_empty + end + it "provides correct #full_gem_path" do + install_gemfile_with_foo_as_a_git_dependency + run <<-RUBY puts Bundler.rubygems.find_name('foo').first.full_gem_path RUBY expect(out).to eq(bundle("info foo --path")) end + + it "does not lock versions that don't exist in the repository when changing a GEM transitive dep to a GIT direct dep" do + build_repo4 do + build_gem "activesupport", "8.0.0" do |s| + s.add_dependency "securerandom" + end + + build_gem "securerandom", "0.3.1" + end + + path = lib_path("securerandom") + + build_git "securerandom", "0.3.2", path: path + + lockfile <<~L + GEM + remote: https://gem.repo4/ + specs: + activesupport (8.0.0) + securerandom + securerandom (0.3.1) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + activesupport + + BUNDLED WITH + #{Bundler::VERSION} + L + + gemfile <<~G + source "https://gem.repo4" + + gem "activesupport" + gem "securerandom", git: "#{path}" + G + + bundle "lock" + + expect(lockfile).to include("securerandom (0.3.2)") + end + + it "does not lock versions that don't exist in the repository when changing a GIT direct dep to a GEM direct dep" do + build_repo4 do + build_gem "ruby-lsp", "0.16.1" + end + + path = lib_path("ruby-lsp") + revision = build_git("ruby-lsp", "0.16.2", path: path).ref_for("HEAD") + + lockfile <<~L + GIT + remote: #{path} + revision: #{revision} + specs: + ruby-lsp (0.16.2) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + ruby-lsp! + + BUNDLED WITH + #{Bundler::VERSION} + L + + gemfile <<~G + source "https://gem.repo4" + gem "ruby-lsp" + G + + bundle "lock" + + expect(lockfile).to include("ruby-lsp (0.16.1)") + end end diff --git a/spec/bundler/lock/lockfile_bundler_1_spec.rb b/spec/bundler/lock/lockfile_bundler_1_spec.rb deleted file mode 100644 index 3be45e29dc..0000000000 --- a/spec/bundler/lock/lockfile_bundler_1_spec.rb +++ /dev/null @@ -1,1386 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe "the lockfile format", :bundler => "< 2" do - include Bundler::GemHelpers - - before { ENV["BUNDLER_SPEC_IGNORE_COMPATIBILITY_GUARD"] = "TRUE" } - - it "generates a simple lockfile for a single source, gem" do - install_gemfile <<-G - source "file://#{gem_repo1}" - - gem "rack" - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - rack - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "updates the lockfile's bundler version if current ver. is newer" do - lockfile <<-L - GIT - remote: git://github.com/nex3/haml.git - revision: 8a2271f - specs: - - GEM - remote: file://#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - omg! - rack - - BUNDLED WITH - 1.8.2 - L - - install_gemfile <<-G - source "file://#{gem_repo1}" - - gem "rack" - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - rack - - BUNDLED WITH - #{Bundler::VERSION} - 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.0.a" - - lockfile <<-L - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - rack - - BUNDLED WITH - #{version} - L - - install_gemfile <<-G - source "file://#{gem_repo1}" - - gem "rack" - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - rack - - BUNDLED WITH - #{version} - G - end - - it "updates the lockfile's bundler version if not present" do - lockfile <<-L - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - rack - L - - install_gemfile <<-G - source "file://#{gem_repo1}" - - gem "rack", "> 0" - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - rack (> 0) - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "outputs a warning if the current is older than lockfile's bundler version" do - lockfile <<-L - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - rack - - BUNDLED WITH - 9999999.1.0 - L - - simulate_bundler_version "9999999.0.0" do - install_gemfile <<-G - source "file://#{gem_repo1}" - - gem "rack" - G - end - - warning_message = "the running version of Bundler (9999999.0.0) is older " \ - "than the version that created the lockfile (9999999.1.0)" - expect(out.scan(warning_message).size).to eq(1) - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - #{generic_local_platform} - #{specific_local_platform} - - DEPENDENCIES - rack - - BUNDLED WITH - 9999999.1.0 - G - end - - it "errors if the current is a major version older than lockfile's bundler version" do - lockfile <<-L - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - rack - - BUNDLED WITH - 9999999.0.0 - L - - install_gemfile <<-G - source "file://#{gem_repo1}" - - gem "rack" - G - - expect(exitstatus > 0) if exitstatus - expect(out).to include("You must use Bundler 9999999 or greater with this lockfile.") - end - - it "shows a friendly error when running with a new bundler 2 lockfile" do - lockfile <<-L - GEM - remote: https://rails-assets.org/ - specs: - rails-assets-bootstrap (3.3.4) - rails-assets-jquery (>= 1.9.1) - rails-assets-jquery (2.1.4) - - GEM - remote: https://rubygems.org/ - specs: - rake (10.4.2) - - PLATFORMS - ruby - - DEPENDENCIES - rails-assets-bootstrap! - rake - - BUNDLED WITH - 9999999.0.0 - L - - install_gemfile <<-G - source 'https://rubygems.org' - gem 'rake' - - source 'https://rails-assets.org' do - gem 'rails-assets-bootstrap' - end - G - - expect(exitstatus > 0) if exitstatus - expect(out).to include("You must use Bundler 9999999 or greater with this lockfile.") - end - - it "warns when updating bundler major version" do - lockfile <<-L - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - rack - - BUNDLED WITH - 1.10.0 - L - - simulate_bundler_version "9999999.0.0" do - install_gemfile <<-G - source "file://#{gem_repo1}" - - gem "rack" - G - end - - expect(out).to include("Warning: the lockfile is being updated to Bundler " \ - "9999999, after which you will be unable to return to Bundler 1.") - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - #{generic_local_platform} - #{specific_local_platform} - - DEPENDENCIES - rack - - BUNDLED WITH - 9999999.0.0 - G - end - - it "generates a simple lockfile for a single source, gem with dependencies" do - install_gemfile <<-G - source "file://#{gem_repo1}" - - gem "rack-obama" - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - rack-obama (1.0) - rack - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - rack-obama - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "generates a simple lockfile for a single source, gem with a version requirement" do - install_gemfile <<-G - source "file://#{gem_repo1}" - - gem "rack-obama", ">= 1.0" - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - rack-obama (1.0) - rack - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - rack-obama (>= 1.0) - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "generates a lockfile wihout credentials for a configured source" do - bundle "config http://localgemserver.test/ user:pass" - - install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true) - source "http://localgemserver.test/" - source "http://user:pass@othergemserver.test/" - - gem "rack-obama", ">= 1.0" - G - - lockfile_should_be <<-G - GEM - remote: http://localgemserver.test/ - remote: http://user:pass@othergemserver.test/ - specs: - rack (1.0.0) - rack-obama (1.0) - rack - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - rack-obama (>= 1.0) - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "generates lockfiles with multiple requirements" do - install_gemfile <<-G - source "file://#{gem_repo1}" - gem "net-sftp" - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - net-sftp (1.1.1) - net-ssh (>= 1.0.0, < 1.99.0) - net-ssh (1.0) - - PLATFORMS - ruby - - DEPENDENCIES - net-sftp - - BUNDLED WITH - #{Bundler::VERSION} - G - - expect(the_bundle).to include_gems "net-sftp 1.1.1", "net-ssh 1.0.0" - end - - it "generates a simple lockfile for a single pinned source, gem with a version requirement" do - git = build_git "foo" - - install_gemfile <<-G - gem "foo", :git => "#{lib_path("foo-1.0")}" - G - - lockfile_should_be <<-G - GIT - remote: #{lib_path("foo-1.0")} - revision: #{git.ref_for("master")} - specs: - foo (1.0) - - GEM - specs: - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - foo! - - 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") - - gemfile <<-G - source "file://#{gem_repo1}" - - platforms :#{not_local_tag} do - gem "omg", :path => "#{lib_path("omg")}" - end - - gem "rack" - G - - lockfile <<-L - GIT - remote: git://github.com/nex3/haml.git - revision: 8a2271f - specs: - - GEM - remote: file://#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - #{not_local} - - DEPENDENCIES - omg! - rack - - BUNDLED WITH - #{Bundler::VERSION} - L - - bundle "install" - expect(the_bundle).to include_gems "rack 1.0.0" - end - - it "serializes global git sources" do - git = build_git "foo" - - install_gemfile <<-G - git "#{lib_path("foo-1.0")}" do - gem "foo" - end - G - - lockfile_should_be <<-G - GIT - remote: #{lib_path("foo-1.0")} - revision: #{git.ref_for("master")} - specs: - foo (1.0) - - GEM - specs: - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - foo! - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - 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" - - install_gemfile <<-G - gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "omg" - G - - lockfile_should_be <<-G - GIT - remote: #{lib_path("foo-1.0")} - revision: #{git.ref_for("omg")} - branch: omg - specs: - foo (1.0) - - GEM - specs: - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - foo! - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - 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" - - install_gemfile <<-G - gem "foo", :git => "#{lib_path("foo-1.0")}", :tag => "omg" - G - - lockfile_should_be <<-G - GIT - remote: #{lib_path("foo-1.0")} - revision: #{git.ref_for("omg")} - tag: omg - specs: - foo (1.0) - - GEM - specs: - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - foo! - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "serializes pinned path sources to the lockfile" do - build_lib "foo" - - install_gemfile <<-G - gem "foo", :path => "#{lib_path("foo-1.0")}" - G - - lockfile_should_be <<-G - PATH - remote: #{lib_path("foo-1.0")} - specs: - foo (1.0) - - GEM - specs: - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - foo! - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "serializes pinned path sources to the lockfile even when packaging" do - build_lib "foo" - - install_gemfile! <<-G - gem "foo", :path => "#{lib_path("foo-1.0")}" - G - - bundle! :package, forgotten_command_line_options([:all, :cache_all] => true) - bundle! :install, :local => true - - lockfile_should_be <<-G - PATH - remote: #{lib_path("foo-1.0")} - specs: - foo (1.0) - - GEM - specs: - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - foo! - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "sorts serialized sources by type" do - build_lib "foo" - bar = build_git "bar" - - install_gemfile <<-G - source "file://#{gem_repo1}" - - gem "rack" - gem "foo", :path => "#{lib_path("foo-1.0")}" - gem "bar", :git => "#{lib_path("bar-1.0")}" - G - - lockfile_should_be <<-G - GIT - remote: #{lib_path("bar-1.0")} - revision: #{bar.ref_for("master")} - specs: - bar (1.0) - - PATH - remote: #{lib_path("foo-1.0")} - specs: - foo (1.0) - - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - bar! - foo! - rack - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "lists gems alphabetically" do - install_gemfile <<-G - source "file://#{gem_repo1}" - - gem "thin" - gem "actionpack" - gem "rack-obama" - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - actionpack (2.3.2) - activesupport (= 2.3.2) - activesupport (2.3.2) - rack (1.0.0) - rack-obama (1.0) - rack - thin (1.0) - rack - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - actionpack - rack-obama - thin - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "orders dependencies' dependencies in alphabetical order" do - install_gemfile <<-G - source "file://#{gem_repo1}" - - gem "rails" - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - actionmailer (2.3.2) - activesupport (= 2.3.2) - actionpack (2.3.2) - activesupport (= 2.3.2) - activerecord (2.3.2) - activesupport (= 2.3.2) - activeresource (2.3.2) - activesupport (= 2.3.2) - activesupport (2.3.2) - rails (2.3.2) - actionmailer (= 2.3.2) - actionpack (= 2.3.2) - activerecord (= 2.3.2) - activeresource (= 2.3.2) - rake (= 10.0.2) - rake (10.0.2) - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - rails - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "orders dependencies by version" do - install_gemfile <<-G - source "file://#{gem_repo1}" - gem 'double_deps' - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - double_deps (1.0) - net-ssh - net-ssh (>= 1.0.0) - net-ssh (1.0) - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - double_deps - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "does not add the :require option to the lockfile" do - install_gemfile <<-G - source "file://#{gem_repo1}" - - gem "rack-obama", ">= 1.0", :require => "rack/obama" - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - rack-obama (1.0) - rack - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - rack-obama (>= 1.0) - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "does not add the :group option to the lockfile" do - install_gemfile <<-G - source "file://#{gem_repo1}" - - gem "rack-obama", ">= 1.0", :group => :test - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - rack-obama (1.0) - rack - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - rack-obama (>= 1.0) - - 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") - - install_gemfile <<-G - path "foo" - gem "foo" - G - - lockfile_should_be <<-G - PATH - remote: foo - specs: - foo (1.0) - - GEM - specs: - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - foo - - 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")) - - install_gemfile <<-G - path "../foo" - gem "foo" - G - - lockfile_should_be <<-G - PATH - remote: ../foo - specs: - foo (1.0) - - GEM - specs: - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - foo - - 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") - - install_gemfile <<-G - path File.expand_path("../foo", __FILE__) - gem "foo" - G - - lockfile_should_be <<-G - PATH - remote: foo - specs: - foo (1.0) - - GEM - specs: - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - foo - - 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")) - - install_gemfile <<-G - gemspec :path => "../foo" - G - - lockfile_should_be <<-G - PATH - remote: ../foo - specs: - foo (1.0) - - GEM - specs: - - PLATFORMS - #{generic_local_platform} - - DEPENDENCIES - foo! - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "keeps existing platforms in the lockfile" do - lockfile <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - java - - DEPENDENCIES - rack - - BUNDLED WITH - #{Bundler::VERSION} - G - - install_gemfile <<-G - source "file://#{gem_repo1}" - - gem "rack" - G - - platforms = ["java", generic_local_platform.to_s].sort - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - #{platforms[0]} - #{platforms[1]} - - DEPENDENCIES - rack - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "persists the spec's platform to the lockfile" do - build_gem "platform_specific", "1.0.0", :to_system => true do |s| - s.platform = Gem::Platform.new("universal-java-16") - end - - simulate_platform "universal-java-16" - - install_gemfile <<-G - source "file://#{gem_repo1}" - gem "platform_specific" - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - platform_specific (1.0-java) - - PLATFORMS - java - - DEPENDENCIES - platform_specific - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "does not add duplicate gems" do - install_gemfile <<-G - source "file://#{gem_repo1}" - gem "rack" - G - - install_gemfile <<-G - source "file://#{gem_repo1}" - gem "rack" - gem "activesupport" - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - activesupport (2.3.5) - rack (1.0.0) - - PLATFORMS - ruby - - DEPENDENCIES - activesupport - rack - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "does not add duplicate dependencies" do - install_gemfile <<-G - source "file://#{gem_repo1}" - gem "rack" - gem "rack" - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - ruby - - DEPENDENCIES - rack - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "does not add duplicate dependencies with versions" do - install_gemfile <<-G - source "file://#{gem_repo1}" - gem "rack", "1.0" - gem "rack", "1.0" - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - ruby - - DEPENDENCIES - rack (= 1.0) - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "does not add duplicate dependencies in different groups" do - install_gemfile <<-G - source "file://#{gem_repo1}" - gem "rack", "1.0", :group => :one - gem "rack", "1.0", :group => :two - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - - PLATFORMS - ruby - - DEPENDENCIES - rack (= 1.0) - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "raises if two different versions are used" do - install_gemfile <<-G - source "file://#{gem_repo1}" - gem "rack", "1.0" - gem "rack", "1.1" - G - - expect(bundled_app("Gemfile.lock")).not_to exist - expect(out).to include "rack (= 1.0) and rack (= 1.1)" - end - - it "raises if two different sources are used" do - install_gemfile <<-G - source "file://#{gem_repo1}" - gem "rack" - gem "rack", :git => "git://hubz.com" - G - - expect(bundled_app("Gemfile.lock")).not_to exist - expect(out).to include "rack (>= 0) should come from an unspecified source and git://hubz.com (at master)" - end - - it "works correctly with multiple version dependencies" do - install_gemfile <<-G - source "file://#{gem_repo1}" - gem "rack", "> 0.9", "< 1.0" - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (0.9.1) - - PLATFORMS - ruby - - DEPENDENCIES - rack (> 0.9, < 1.0) - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "captures the Ruby version in the lockfile" do - install_gemfile <<-G - source "file://#{gem_repo1}" - ruby '#{RUBY_VERSION}' - gem "rack", "> 0.9", "< 1.0" - G - - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (0.9.1) - - PLATFORMS - ruby - - DEPENDENCIES - rack (> 0.9, < 1.0) - - RUBY VERSION - ruby #{RUBY_VERSION}p#{RUBY_PATCHLEVEL} - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - # Some versions of the Bundler 1.1 RC series introduced corrupted - # lockfiles. There were two major problems: - # - # * multiple copies of the same GIT section appeared in the lockfile - # * when this happened, those sections got multiple copies of gems - # in those sections. - it "fixes corrupted lockfiles" do - build_git "omg", :path => lib_path("omg") - revision = revision_for(lib_path("omg")) - - gemfile <<-G - source "file://#{gem_repo1}" - gem "omg", :git => "#{lib_path("omg")}", :branch => 'master' - G - - bundle "install --path vendor" - expect(the_bundle).to include_gems "omg 1.0" - - # Create a Gemfile.lock that has duplicate GIT sections - lockfile <<-L - GIT - remote: #{lib_path("omg")} - revision: #{revision} - branch: master - specs: - omg (1.0) - - GIT - remote: #{lib_path("omg")} - revision: #{revision} - branch: master - specs: - omg (1.0) - - GEM - remote: file:#{gem_repo1}/ - specs: - - PLATFORMS - #{local} - - DEPENDENCIES - omg! - - BUNDLED WITH - #{Bundler::VERSION} - L - - FileUtils.rm_rf(bundled_app("vendor")) - bundle "install" - expect(the_bundle).to include_gems "omg 1.0" - - # Confirm that duplicate specs do not appear - expect(File.read(bundled_app("Gemfile.lock"))).to eq(strip_whitespace(<<-L)) - GIT - remote: #{lib_path("omg")} - revision: #{revision} - branch: master - specs: - omg (1.0) - - GEM - remote: file:#{gem_repo1}/ - specs: - - PLATFORMS - #{local} - - DEPENDENCIES - omg! - - BUNDLED WITH - #{Bundler::VERSION} - L - end - - it "raises a helpful error message when the lockfile is missing deps" do - lockfile <<-L - GEM - remote: file:#{gem_repo1}/ - specs: - rack_middleware (1.0) - - PLATFORMS - #{local} - - DEPENDENCIES - rack_middleware - L - - install_gemfile <<-G - source "file:#{gem_repo1}" - gem "rack_middleware" - G - - expect(out).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.") - end - - describe "a line ending" do - def set_lockfile_mtime_to_known_value - time = Time.local(2000, 1, 1, 0, 0, 0) - File.utime(time, time, bundled_app("Gemfile.lock")) - end - before(:each) do - build_repo2 - - install_gemfile <<-G - source "file://#{gem_repo2}" - gem "rack" - G - set_lockfile_mtime_to_known_value - end - - it "generates Gemfile.lock with \\n line endings" do - expect(File.read(bundled_app("Gemfile.lock"))).not_to match("\r\n") - expect(the_bundle).to include_gems "rack 1.0" - end - - context "during updates" do - it "preserves Gemfile.lock \\n line endings" do - update_repo2 - - expect { bundle "update", :all => true }.to change { File.mtime(bundled_app("Gemfile.lock")) } - expect(File.read(bundled_app("Gemfile.lock"))).not_to match("\r\n") - expect(the_bundle).to include_gems "rack 1.2" - end - - it "preserves Gemfile.lock \\n\\r line endings" do - update_repo2 - win_lock = File.read(bundled_app("Gemfile.lock")).gsub(/\n/, "\r\n") - File.open(bundled_app("Gemfile.lock"), "wb") {|f| f.puts(win_lock) } - set_lockfile_mtime_to_known_value - - expect { bundle "update", :all => true }.to change { File.mtime(bundled_app("Gemfile.lock")) } - expect(File.read(bundled_app("Gemfile.lock"))).to match("\r\n") - expect(the_bundle).to include_gems "rack 1.2" - end - end - - context "when nothing changes" do - it "preserves Gemfile.lock \\n line endings" do - expect do - ruby <<-RUBY - require 'rubygems' - require 'bundler' - Bundler.setup - RUBY - end.not_to change { File.mtime(bundled_app("Gemfile.lock")) } - end - - it "preserves Gemfile.lock \\n\\r line endings" do - win_lock = File.read(bundled_app("Gemfile.lock")).gsub(/\n/, "\r\n") - File.open(bundled_app("Gemfile.lock"), "wb") {|f| f.puts(win_lock) } - set_lockfile_mtime_to_known_value - - expect do - ruby <<-RUBY - require 'rubygems' - require 'bundler' - Bundler.setup - RUBY - end.not_to change { File.mtime(bundled_app("Gemfile.lock")) } - end - end - end - - it "refuses to install if Gemfile.lock contains conflict markers" do - lockfile <<-L - GEM - remote: file://#{gem_repo1}/ - specs: - <<<<<<< - rack (1.0.0) - ======= - rack (1.0.1) - >>>>>>> - - PLATFORMS - ruby - - DEPENDENCIES - rack - - BUNDLED WITH - #{Bundler::VERSION} - L - - install_gemfile(<<-G) - source "file://#{gem_repo1}" - gem "rack" - G - - expect(last_command.bundler_err).to match(/your Gemfile.lock contains merge conflicts/i) - expect(last_command.bundler_err).to match(/git checkout HEAD -- Gemfile.lock/i) - end -end diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb index b4bf81ded2..654ac02aa7 100644 --- a/spec/bundler/lock/lockfile_spec.rb +++ b/spec/bundler/lock/lockfile_spec.rb @@ -1,35 +1,41 @@ # frozen_string_literal: true -RSpec.describe "the lockfile format", :bundler => "2" do - include Bundler::GemHelpers - - before { ENV["BUNDLER_SPEC_IGNORE_COMPATIBILITY_GUARD"] = "TRUE" } +RSpec.describe "the lockfile format" do + before do + build_repo2 + end it "generates a simple lockfile for a single source, gem" do + checksums = checksums_section_when_enabled do |c| + c.checksum(gem_repo2, "myrack", "1.0.0") + end + install_gemfile <<-G - source "file://#{gem_repo1}" + source "https://gem.repo2" - gem "rack" + gem "myrack" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: - rack (1.0.0) + myrack (1.0.0) PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack - + myrack + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{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 GIT remote: git://github.com/nex3/haml.git @@ -37,348 +43,373 @@ RSpec.describe "the lockfile format", :bundler => "2" do specs: GEM - remote: file://#{gem_repo1}/ + remote: https://gem.repo2/ specs: - rack (1.0.0) + myrack (1.0.0) PLATFORMS #{lockfile_platforms} DEPENDENCIES omg! - rack + myrack BUNDLED WITH 1.8.2 L - install_gemfile <<-G - source "file://#{gem_repo1}" + install_gemfile <<-G, verbose: true, env: { "BUNDLER_VERSION" => Bundler::VERSION } + source "https://gem.repo2" - gem "rack" + gem "myrack" 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:#{gem_repo1}/ + remote: https://gem.repo2/ specs: - rack (1.0.0) + myrack (1.0.0) PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack + myrack BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} 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.0.a" + it "does not update the lockfile's bundler version if nothing changed during bundle install, but uses the locked version" do + version = "2.3.0" + + build_repo4 do + build_gem "myrack", "1.0.0" + + build_bundler version + end lockfile <<-L GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo4/ specs: - rack (1.0.0) + myrack (1.0.0) PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack + myrack BUNDLED WITH #{version} L - install_gemfile <<-G - source "file://#{gem_repo1}" + install_gemfile <<-G, verbose: true + source "https://gem.repo4" - gem "rack" + gem "myrack" G - lockfile_should_be <<-G + expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{version}.") + expect(out).to include("Using bundler #{version}") + + expect(lockfile).to eq <<~G GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo4/ specs: - rack (1.0.0) + myrack (1.0.0) PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack + myrack BUNDLED WITH #{version} G end - it "updates the lockfile's bundler version if not present" do + it "adds the BUNDLED WITH section if not present" do lockfile <<-L GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: - rack (1.0.0) + myrack (1.0.0) PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack + myrack L install_gemfile <<-G - source "file://#{gem_repo1}" + source "https://gem.repo2" - gem "rack", "> 0" + gem "myrack", "> 0" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: - rack (1.0.0) + myrack (1.0.0) PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack (> 0) + myrack (> 0) BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G end - it "outputs a warning if the current is older than lockfile's bundler version" do + it "update the bundler major version just fine" do + current_version = Bundler::VERSION + older_major = previous_major(current_version) + + system_gems "bundler-#{older_major}" + lockfile <<-L GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: - rack (1.0.0) + myrack (1.0.0) PLATFORMS - #{generic_local_platform} + #{lockfile_platforms} DEPENDENCIES - rack + myrack BUNDLED WITH - 9999999.1.0 + #{older_major} L - simulate_bundler_version "9999999.0.0" do - install_gemfile <<-G - source "file://#{gem_repo1}" + install_gemfile <<-G, env: { "BUNDLER_VERSION" => Bundler::VERSION } + source "https://gem.repo2/" - gem "rack" - G - end + gem "myrack" + G - warning_message = "the running version of Bundler (9999999.0.0) is older " \ - "than the version that created the lockfile (9999999.1.0)" - expect(last_command.bundler_err).to include warning_message + expect(err).to be_empty - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: - rack (1.0.0) + myrack (1.0.0) PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack + myrack BUNDLED WITH - 9999999.1.0 + #{current_version} G end - it "errors if the current is a major version older than lockfile's bundler version" do - lockfile <<-L + it "generates a simple lockfile for a single source, gem with dependencies" do + install_gemfile <<-G + source "https://gem.repo2/" + + gem "myrack-obama" + G + + checksums = checksums_section_when_enabled do |c| + c.checksum gem_repo2, "myrack", "1.0.0" + c.checksum gem_repo2, "myrack-obama", "1.0" + end + + expect(lockfile).to eq <<~G GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: - rack (1.0.0) + myrack (1.0.0) + myrack-obama (1.0) + myrack PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack - + myrack-obama + #{checksums} BUNDLED WITH - 9999999.0.0 - L + #{Bundler::VERSION} + G + end + it "generates a simple lockfile for a single source, gem with a version requirement" do install_gemfile <<-G - source "file://#{gem_repo1}" + source "https://gem.repo2/" - gem "rack" + gem "myrack-obama", ">= 1.0" G - expect(last_command).to be_failure - expect(last_command.bundler_err).to include("You must use Bundler 9999999 or greater with this lockfile.") - end - - it "shows a friendly error when running with a new bundler 2 lockfile" do - lockfile <<-L - GEM - remote: https://rails-assets.org/ - specs: - rails-assets-bootstrap (3.3.4) - rails-assets-jquery (>= 1.9.1) - rails-assets-jquery (2.1.4) + checksums = checksums_section_when_enabled do |c| + c.checksum gem_repo2, "myrack", "1.0.0" + c.checksum gem_repo2, "myrack-obama", "1.0" + end + expect(lockfile).to eq <<~G GEM - remote: https://rubygems.org/ + remote: https://gem.repo2/ specs: - rake (10.4.2) + myrack (1.0.0) + myrack-obama (1.0) + myrack PLATFORMS - ruby + #{lockfile_platforms} DEPENDENCIES - rails-assets-bootstrap! - rake - + myrack-obama (>= 1.0) + #{checksums} BUNDLED WITH - 9999999.0.0 - L - - install_gemfile <<-G - source 'https://rubygems.org' - gem 'rake' - - source 'https://rails-assets.org' do - gem 'rails-assets-bootstrap' - end + #{Bundler::VERSION} G - - expect(last_command).to be_failure - expect(out).to include("You must use Bundler 9999999 or greater with this lockfile.") end - it "warns when updating bundler major version" do - lockfile <<-L - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) + it "generates a lockfile without credentials" do + bundle "config set https://localgemserver.test/ user:pass" - PLATFORMS - #{generic_local_platform} + install_gemfile(<<-G, artifice: "endpoint_strict_basic_authentication", quiet: true) + source "https://gem.repo1" - DEPENDENCIES - rack + source "https://localgemserver.test/" do - BUNDLED WITH - 1.10.0 - L + end - simulate_bundler_version "9999999.0.0" do - install_gemfile <<-G - source "file://#{gem_repo1}" + source "https://user:pass@othergemserver.test/" do + gem "myrack-obama", ">= 1.0" + end + G - gem "rack" - G + checksums = checksums_section_when_enabled do |c| + c.checksum gem_repo2, "myrack", "1.0.0" + c.checksum gem_repo2, "myrack-obama", "1.0" end - expect(out).to include("Warning: the lockfile is being updated to Bundler " \ - "9999999, after which you will be unable to return to Bundler 1.") + expect(lockfile).to eq <<~G + GEM + remote: https://gem.repo1/ + specs: + + GEM + remote: https://localgemserver.test/ + specs: - lockfile_should_be <<-G GEM - remote: file:#{gem_repo1}/ + remote: https://othergemserver.test/ specs: - rack (1.0.0) + myrack (1.0.0) + myrack-obama (1.0) + myrack PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack - + myrack-obama (>= 1.0)! + #{checksums} BUNDLED WITH - 9999999.0.0 + #{Bundler::VERSION} G end - it "generates a simple lockfile for a single source, gem with dependencies" do - install_gemfile <<-G - source "file://#{gem_repo1}" + it "does not add credentials to lockfile when it does not have them already" do + bundle "config set http://localgemserver.test/ user:pass" - gem "rack-obama" - G + gemfile <<~G + source "https://gem.repo1" - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - rack-obama (1.0) - rack - - PLATFORMS - #{lockfile_platforms} + source "http://localgemserver.test/" do - DEPENDENCIES - rack-obama + end - BUNDLED WITH - #{Bundler::VERSION} + source "http://user:pass@othergemserver.test/" do + gem "myrack-obama", ">= 1.0" + end G - end - it "generates a simple lockfile for a single source, gem with a version requirement" do - install_gemfile <<-G - source "file://#{gem_repo1}" + checksums = checksums_section_when_enabled do |c| + c.checksum gem_repo2, "myrack", "1.0.0" + c.checksum gem_repo2, "myrack-obama", "1.0" + end - gem "rack-obama", ">= 1.0" - G + lockfile_without_credentials = <<~L + GEM + remote: http://localgemserver.test/ + specs: - lockfile_should_be <<-G GEM - remote: file:#{gem_repo1}/ + remote: http://othergemserver.test/ + specs: + myrack (1.0.0) + myrack-obama (1.0) + myrack + + GEM + remote: https://gem.repo1/ specs: - rack (1.0.0) - rack-obama (1.0) - rack PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack-obama (>= 1.0) - + myrack-obama (>= 1.0)! + #{checksums} BUNDLED WITH - #{Bundler::VERSION} - G + #{Bundler::VERSION} + L + + lockfile lockfile_without_credentials + + # when not re-resolving + bundle "install", artifice: "endpoint_strict_basic_authentication", quiet: true + expect(lockfile).to eq lockfile_without_credentials + + # when re-resolving with full unlock + bundle "update", artifice: "endpoint_strict_basic_authentication" + expect(lockfile).to eq lockfile_without_credentials + + # when re-resolving without ful unlocking + bundle "update myrack-obama", artifice: "endpoint_strict_basic_authentication" + expect(lockfile).to eq lockfile_without_credentials end - it "generates a lockfile without credentials for a configured source" do - bundle "config http://localgemserver.test/ user:pass" + it "keeps credentials in lockfile if already there" do + bundle "config set http://localgemserver.test/ user:pass" + + gemfile <<~G + source "https://gem.repo1" - install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true) source "http://localgemserver.test/" do end source "http://user:pass@othergemserver.test/" do - gem "rack-obama", ">= 1.0" + gem "myrack-obama", ">= 1.0" end G - lockfile_should_be <<-G - GEM - specs: + checksums = checksums_section_when_enabled do |c| + c.checksum gem_repo2, "myrack", "1.0.0" + c.checksum gem_repo2, "myrack-obama", "1.0" + end + lockfile_with_credentials = <<~L GEM remote: http://localgemserver.test/ specs: @@ -386,30 +417,45 @@ RSpec.describe "the lockfile format", :bundler => "2" do GEM remote: http://user:pass@othergemserver.test/ specs: - rack (1.0.0) - rack-obama (1.0) - rack + myrack (1.0.0) + myrack-obama (1.0) + myrack + + GEM + remote: https://gem.repo1/ + specs: PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack-obama (>= 1.0)! - + myrack-obama (>= 1.0)! + #{checksums} BUNDLED WITH - #{Bundler::VERSION} - G + #{Bundler::VERSION} + L + + lockfile lockfile_with_credentials + + bundle "install", artifice: "endpoint_strict_basic_authentication", quiet: true + + expect(lockfile).to eq lockfile_with_credentials end it "generates lockfiles with multiple requirements" do install_gemfile <<-G - source "file://#{gem_repo1}" + source "https://gem.repo2/" gem "net-sftp" G - lockfile_should_be <<-G + checksums = checksums_section_when_enabled 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:#{gem_repo1}/ + remote: https://gem.repo2/ specs: net-sftp (1.1.1) net-ssh (>= 1.0.0, < 1.99.0) @@ -420,29 +466,35 @@ RSpec.describe "the lockfile format", :bundler => "2" do DEPENDENCIES net-sftp - + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G expect(the_bundle).to include_gems "net-sftp 1.1.1", "net-ssh 1.0.0" end - it "generates a simple lockfile for a single pinned source, gem with a version requirement", :bundler => "< 2" do + it "generates a simple lockfile for a single pinned source, gem with a version requirement" do git = build_git "foo" install_gemfile <<-G + source "https://gem.repo1" gem "foo", :git => "#{lib_path("foo-1.0")}" G - lockfile_should_be <<-G + checksums = checksums_section_when_enabled 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) GEM + remote: https://gem.repo1/ specs: PLATFORMS @@ -450,51 +502,23 @@ RSpec.describe "the lockfile format", :bundler => "2" do DEPENDENCIES foo! - + #{checksums} BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "generates a simple lockfile for a single pinned source, gem with a version requirement" do - git = build_git "foo" - - install_gemfile <<-G - gem "foo", :git => "#{lib_path("foo-1.0")}" - G - - lockfile_should_be <<-G - GEM - specs: - - GIT - remote: #{lib_path("foo-1.0")} - revision: #{git.ref_for("master")} - specs: - foo (1.0) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - foo! - - BUNDLED WITH - #{Bundler::VERSION} + #{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://#{gem_repo1}" + source "https://gem.repo2/" platforms :#{not_local_tag} do gem "omg", :path => "#{lib_path("omg")}" end - gem "rack" + gem "myrack" G lockfile <<-L @@ -504,67 +528,75 @@ RSpec.describe "the lockfile format", :bundler => "2" do specs: GEM - remote: file://#{gem_repo1}/ + remote: https://gem.repo2// specs: - rack (1.0.0) + myrack (1.0.0) PLATFORMS #{not_local} DEPENDENCIES omg! - rack + myrack BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} L - bundle! "install" - expect(the_bundle).to include_gems "rack 1.0.0" + bundle "install" + expect(the_bundle).to include_gems "myrack 1.0.0" end it "serializes global git sources" do git = build_git "foo" + checksums = checksums_section_when_enabled do |c| + c.no_checksum "foo", "1.0" + end + install_gemfile <<-G + source "https://gem.repo1" git "#{lib_path("foo-1.0")}" do gem "foo" end G - lockfile_should_be <<-G - GEM - specs: - + 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) + GEM + remote: https://gem.repo1/ + specs: + PLATFORMS #{lockfile_platforms} DEPENDENCIES foo! - + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G end 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_enabled do |c| + c.no_checksum "foo", "1.0" + end install_gemfile <<-G + source "https://gem.repo1" gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "omg" G - lockfile_should_be <<-G - GEM - specs: - + expect(lockfile).to eq <<~G GIT remote: #{lib_path("foo-1.0")} revision: #{git.ref_for("omg")} @@ -572,29 +604,35 @@ RSpec.describe "the lockfile format", :bundler => "2" do specs: foo (1.0) + GEM + remote: https://gem.repo1/ + specs: + PLATFORMS #{lockfile_platforms} DEPENDENCIES foo! - + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G end 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_enabled do |c| + c.no_checksum "foo", "1.0" + end install_gemfile <<-G + source "https://gem.repo1" gem "foo", :git => "#{lib_path("foo-1.0")}", :tag => "omg" G - lockfile_should_be <<-G - GEM - specs: - + expect(lockfile).to eq <<~G GIT remote: #{lib_path("foo-1.0")} revision: #{git.ref_for("omg")} @@ -602,71 +640,173 @@ RSpec.describe "the lockfile format", :bundler => "2" do specs: foo (1.0) + GEM + remote: https://gem.repo1/ + specs: + PLATFORMS #{lockfile_platforms} DEPENDENCIES foo! - + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{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: @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 "https://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: https://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: https://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_enabled do |c| + c.no_checksum "foo", "1.0" + end + install_gemfile <<-G + source "https://gem.repo1" gem "foo", :path => "#{lib_path("foo-1.0")}" G - lockfile_should_be <<-G - GEM - specs: - + expect(lockfile).to eq <<~G PATH remote: #{lib_path("foo-1.0")} specs: foo (1.0) + GEM + remote: https://gem.repo1/ + specs: + PLATFORMS #{lockfile_platforms} DEPENDENCIES foo! - + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G end it "serializes pinned path sources to the lockfile even when packaging" do build_lib "foo" - install_gemfile! <<-G + install_gemfile <<-G + source "https://gem.repo1" gem "foo", :path => "#{lib_path("foo-1.0")}" G - bundle! :package, forgotten_command_line_options([:all, :cache_all] => true) - bundle! :install, :local => true + checksums = checksums_section_when_enabled do |c| + c.no_checksum "foo", "1.0" + end - lockfile_should_be <<-G - GEM - specs: + bundle :cache + bundle :install, local: true + expect(lockfile).to eq <<~G PATH remote: #{lib_path("foo-1.0")} specs: foo (1.0) + GEM + remote: https://gem.repo1/ + specs: + PLATFORMS #{lockfile_platforms} DEPENDENCIES foo! - + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G end @@ -674,23 +814,24 @@ RSpec.describe "the lockfile format", :bundler => "2" do build_lib "foo" bar = build_git "bar" + checksums = checksums_section_when_enabled do |c| + c.no_checksum "foo", "1.0" + c.no_checksum "bar", "1.0" + c.checksum gem_repo2, "myrack", "1.0.0" + end + install_gemfile <<-G - source "file://#{gem_repo1}" + source "https://gem.repo2/" - gem "rack" + gem "myrack" gem "foo", :path => "#{lib_path("foo-1.0")}" gem "bar", :git => "#{lib_path("bar-1.0")}" G - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo1}/ - specs: - rack (1.0.0) - + 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) @@ -699,64 +840,115 @@ RSpec.describe "the lockfile format", :bundler => "2" do specs: foo (1.0) + GEM + remote: https://gem.repo2/ + specs: + myrack (1.0.0) + PLATFORMS #{lockfile_platforms} DEPENDENCIES bar! foo! - rack + myrack + #{checksums} + BUNDLED WITH + #{Bundler::VERSION} + G + end + + it "removes redundant sources" do + install_gemfile <<-G + source "https://gem.repo2/" + + gem "myrack", :source => "https://gem.repo2/" + G + checksums = checksums_section_when_enabled do |c| + c.checksum gem_repo2, "myrack", "1.0.0" + end + + expect(lockfile).to eq <<~G + GEM + remote: https://gem.repo2/ + specs: + myrack (1.0.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + myrack! + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G end it "lists gems alphabetically" do install_gemfile <<-G - source "file://#{gem_repo1}" + source "https://gem.repo2/" gem "thin" gem "actionpack" - gem "rack-obama" + gem "myrack-obama" G - lockfile_should_be <<-G + checksums = checksums_section_when_enabled do |c| + c.checksum gem_repo2, "actionpack", "2.3.2" + c.checksum gem_repo2, "activesupport", "2.3.2" + c.checksum gem_repo2, "myrack", "1.0.0" + c.checksum gem_repo2, "myrack-obama", "1.0" + c.checksum gem_repo2, "thin", "1.0" + end + + expect(lockfile).to eq <<~G GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: actionpack (2.3.2) activesupport (= 2.3.2) activesupport (2.3.2) - rack (1.0.0) - rack-obama (1.0) - rack + myrack (1.0.0) + myrack-obama (1.0) + myrack thin (1.0) - rack + myrack PLATFORMS #{lockfile_platforms} DEPENDENCIES actionpack - rack-obama + myrack-obama thin - + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G end it "orders dependencies' dependencies in alphabetical order" do install_gemfile <<-G - source "file://#{gem_repo1}" + source "https://gem.repo2/" gem "rails" G - lockfile_should_be <<-G + checksums = checksums_section_when_enabled 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:#{gem_repo1}/ + remote: https://gem.repo2/ specs: actionmailer (2.3.2) activesupport (= 2.3.2) @@ -772,29 +964,44 @@ RSpec.describe "the lockfile format", :bundler => "2" do actionpack (= 2.3.2) activerecord (= 2.3.2) activeresource (= 2.3.2) - rake (= 10.0.2) - rake (10.0.2) + rake (= #{rake_version}) + rake (#{rake_version}) PLATFORMS #{lockfile_platforms} DEPENDENCIES rails - + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{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/ruby/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://#{gem_repo1}" + source "https://gem.repo2" gem 'double_deps' G - lockfile_should_be <<-G + checksums = checksums_section_when_enabled 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:#{gem_repo1}/ + remote: https://gem.repo2/ specs: double_deps (1.0) net-ssh @@ -806,563 +1013,1343 @@ RSpec.describe "the lockfile format", :bundler => "2" do DEPENDENCIES double_deps - + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G end it "does not add the :require option to the lockfile" do install_gemfile <<-G - source "file://#{gem_repo1}" + source "https://gem.repo2/" - gem "rack-obama", ">= 1.0", :require => "rack/obama" + gem "myrack-obama", ">= 1.0", :require => "myrack/obama" G - lockfile_should_be <<-G + checksums = checksums_section_when_enabled do |c| + c.checksum gem_repo2, "myrack", "1.0.0" + c.checksum gem_repo2, "myrack-obama", "1.0" + end + + expect(lockfile).to eq <<~G GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: - rack (1.0.0) - rack-obama (1.0) - rack + myrack (1.0.0) + myrack-obama (1.0) + myrack PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack-obama (>= 1.0) - + myrack-obama (>= 1.0) + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G end it "does not add the :group option to the lockfile" do install_gemfile <<-G - source "file://#{gem_repo1}" + source "https://gem.repo2/" - gem "rack-obama", ">= 1.0", :group => :test + gem "myrack-obama", ">= 1.0", :group => :test G - lockfile_should_be <<-G + checksums = checksums_section_when_enabled do |c| + c.checksum gem_repo2, "myrack", "1.0.0" + c.checksum gem_repo2, "myrack-obama", "1.0" + end + + expect(lockfile).to eq <<~G GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: - rack (1.0.0) - rack-obama (1.0) - rack + myrack (1.0.0) + myrack-obama (1.0) + myrack PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack-obama (>= 1.0) - + myrack-obama (>= 1.0) + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{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_enabled do |c| + c.no_checksum "foo", "1.0" + end install_gemfile <<-G + source "https://gem.repo1" path "foo" do gem "foo" end G - lockfile_should_be <<-G - GEM - specs: - + expect(lockfile).to eq <<~G PATH remote: foo specs: foo (1.0) + GEM + remote: https://gem.repo1/ + specs: + PLATFORMS #{lockfile_platforms} DEPENDENCIES foo! - + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{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_enabled do |c| + c.no_checksum "foo", "1.0" + end install_gemfile <<-G + source "https://gem.repo1" path "../foo" do gem "foo" end G - lockfile_should_be <<-G - GEM - specs: - + expect(lockfile).to eq <<~G PATH remote: ../foo specs: foo (1.0) + GEM + remote: https://gem.repo1/ + specs: + PLATFORMS #{lockfile_platforms} DEPENDENCIES foo! - + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{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") install_gemfile <<-G - path File.expand_path("../foo", __FILE__) do + source "https://gem.repo1" + path File.expand_path("foo", __dir__) do gem "foo" end G - lockfile_should_be <<-G - GEM - specs: + checksums = checksums_section_when_enabled do |c| + c.no_checksum "foo", "1.0" + end + expect(lockfile).to eq <<~G PATH remote: foo specs: foo (1.0) + GEM + remote: https://gem.repo1/ + specs: + PLATFORMS #{lockfile_platforms} DEPENDENCIES foo! - + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{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("foo")) + + checksums = checksums_section_when_enabled do |c| + c.no_checksum "foo", "1.0" + end install_gemfile <<-G + source "https://gem.repo1" gemspec :path => "../foo" G - lockfile_should_be <<-G - GEM - specs: - + expect(lockfile).to eq <<~G PATH remote: ../foo specs: foo (1.0) + GEM + remote: https://gem.repo1/ + specs: + PLATFORMS #{lockfile_platforms} DEPENDENCIES foo! - + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G end it "keeps existing platforms in the lockfile" do + checksums = checksums_section_when_enabled do |c| + c.no_checksum "myrack", "1.0.0" + end + lockfile <<-G GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: - rack (1.0.0) + myrack (1.0.0) PLATFORMS java DEPENDENCIES - rack - + myrack + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G install_gemfile <<-G - source "file://#{gem_repo1}" + source "https://gem.repo2/" - gem "rack" + gem "myrack" G - lockfile_should_be <<-G + checksums.checksum(gem_repo2, "myrack", "1.0.0") + + expect(lockfile).to eq <<~G GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: - rack (1.0.0) + myrack (1.0.0) PLATFORMS - #{lockfile_platforms "java", generic_local_platform, specific_local_platform} + #{lockfile_platforms("java", local_platform, defaults: [])} DEPENDENCIES - rack - + myrack + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G end - it "persists the spec's platform to the lockfile" do + 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 "https://gem.repo4" + gem "google-protobuf" + G + bundle "lock --add-platform x64-mingw-ucrt" + + checksums = checksums_section_when_enabled do |c| + c.checksum gem_repo4, "google-protobuf", "3.25.1" + c.checksum gem_repo4, "google-protobuf", "3.25.1", "arm64-darwin-23" + end + + expect(lockfile).to eq <<~L + GEM + remote: https://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 + #{checksums} + 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| s.platform = Gem::Platform.new("universal-java-16") end end - simulate_platform "universal-java-16" + simulate_platform "universal-java-16" do + install_gemfile <<-G + source "https://gem.repo2" + gem "platform_specific" + G - install_gemfile! <<-G - source "file://#{gem_repo2}" - gem "platform_specific" - G + checksums = checksums_section_when_enabled do |c| + c.checksum gem_repo2, "platform_specific", "1.0", "universal-java-16" + end - lockfile_should_be <<-G - GEM - remote: file:#{gem_repo2}/ - specs: - platform_specific (1.0-java) - platform_specific (1.0-universal-java-16) + expect(lockfile).to eq <<~G + GEM + remote: https://gem.repo2/ + specs: + platform_specific (1.0-universal-java-16) - PLATFORMS - java - universal-java-16 - - DEPENDENCIES - platform_specific + PLATFORMS + universal-java-16 - BUNDLED WITH - #{Bundler::VERSION} - G + DEPENDENCIES + platform_specific + #{checksums} + BUNDLED WITH + #{Bundler::VERSION} + G + end end it "does not add duplicate gems" do + checksums = checksums_section_when_enabled do |c| + c.checksum(gem_repo2, "activesupport", "2.3.5") + c.checksum(gem_repo2, "myrack", "1.0.0") + end + install_gemfile <<-G - source "file://#{gem_repo1}" - gem "rack" + source "https://gem.repo2/" + gem "myrack" G install_gemfile <<-G - source "file://#{gem_repo1}" - gem "rack" + source "https://gem.repo2/" + gem "myrack" gem "activesupport" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: activesupport (2.3.5) - rack (1.0.0) + myrack (1.0.0) PLATFORMS #{lockfile_platforms} DEPENDENCIES activesupport - rack - + myrack + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G end it "does not add duplicate dependencies" do + checksums = checksums_section_when_enabled do |c| + c.checksum(gem_repo2, "myrack", "1.0.0") + end + install_gemfile <<-G - source "file://#{gem_repo1}" - gem "rack" - gem "rack" + source "https://gem.repo2/" + gem "myrack" + gem "myrack" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: - rack (1.0.0) + myrack (1.0.0) PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack - + myrack + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G end it "does not add duplicate dependencies with versions" do + checksums = checksums_section_when_enabled do |c| + c.checksum(gem_repo2, "myrack", "1.0.0") + end + install_gemfile <<-G - source "file://#{gem_repo1}" - gem "rack", "1.0" - gem "rack", "1.0" + source "https://gem.repo2/" + gem "myrack", "1.0" + gem "myrack", "1.0" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: - rack (1.0.0) + myrack (1.0.0) PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack (= 1.0) - + myrack (= 1.0) + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G end it "does not add duplicate dependencies in different groups" do + checksums = checksums_section_when_enabled do |c| + c.checksum(gem_repo2, "myrack", "1.0.0") + end + install_gemfile <<-G - source "file://#{gem_repo1}" - gem "rack", "1.0", :group => :one - gem "rack", "1.0", :group => :two + source "https://gem.repo2/" + gem "myrack", "1.0", :group => :one + gem "myrack", "1.0", :group => :two G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: - rack (1.0.0) + myrack (1.0.0) PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack (= 1.0) - + myrack (= 1.0) + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G end it "raises if two different versions are used" do - install_gemfile <<-G - source "file://#{gem_repo1}" - gem "rack", "1.0" - gem "rack", "1.1" + install_gemfile <<-G, raise_on_error: false + source "https://gem.repo2/" + gem "myrack", "1.0" + gem "myrack", "1.1" G - expect(bundled_app("Gemfile.lock")).not_to exist - expect(out).to include "rack (= 1.0) and rack (= 1.1)" + expect(bundled_app_lock).not_to exist + expect(err).to include "myrack (= 1.0) and myrack (= 1.1)" end it "raises if two different sources are used" do - install_gemfile <<-G - source "file://#{gem_repo1}" - gem "rack" - gem "rack", :git => "git://hubz.com" + install_gemfile <<-G, raise_on_error: false + source "https://gem.repo2/" + gem "myrack" + gem "myrack", :git => "git://hubz.com" G - expect(bundled_app("Gemfile.lock")).not_to exist - expect(out).to include "rack (>= 0) should come from an unspecified source and git://hubz.com (at master)" + expect(bundled_app_lock).not_to exist + expect(err).to include "myrack (>= 0) should come from an unspecified source and git://hubz.com" end it "works correctly with multiple version dependencies" do + checksums = checksums_section_when_enabled do |c| + c.checksum(gem_repo2, "myrack", "0.9.1") + end + install_gemfile <<-G - source "file://#{gem_repo1}" - gem "rack", "> 0.9", "< 1.0" + source "https://gem.repo2/" + gem "myrack", "> 0.9", "< 1.0" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: - rack (0.9.1) + myrack (0.9.1) PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack (> 0.9, < 1.0) - + myrack (> 0.9, < 1.0) + #{checksums} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G end it "captures the Ruby version in the lockfile" do + checksums = checksums_section_when_enabled do |c| + c.checksum(gem_repo2, "myrack", "0.9.1") + end + install_gemfile <<-G - source "file://#{gem_repo1}" - ruby '#{RUBY_VERSION}' - gem "rack", "> 0.9", "< 1.0" + source "https://gem.repo2/" + ruby '#{Gem.ruby_version}' + gem "myrack", "> 0.9", "< 1.0" G - lockfile_should_be <<-G + expect(lockfile).to eq <<~G GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: - rack (0.9.1) + myrack (0.9.1) PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack (> 0.9, < 1.0) - + myrack (> 0.9, < 1.0) + #{checksums} RUBY VERSION - ruby #{RUBY_VERSION}p#{RUBY_PATCHLEVEL} + #{Bundler::RubyVersion.system} BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} G end - # Some versions of the Bundler 1.1 RC series introduced corrupted - # lockfiles. There were two major problems: - # - # * multiple copies of the same GIT section appeared in the lockfile - # * when this happened, those sections got multiple copies of gems - # in those sections. - it "fixes corrupted lockfiles" do - build_git "omg", :path => lib_path("omg") - revision = revision_for(lib_path("omg")) + it "automatically fixes the lockfile when it's missing deps" do + lockfile <<-L + GEM + remote: https://gem.repo2/ + specs: + myrack_middleware (1.0) + + PLATFORMS + #{lockfile_platforms} - gemfile <<-G - source "file://#{gem_repo1}" - gem "omg", :git => "#{lib_path("omg")}", :branch => 'master' + DEPENDENCIES + myrack_middleware + + BUNDLED WITH + #{Bundler::VERSION} + L + + install_gemfile <<-G + source "https://gem.repo2" + gem "myrack_middleware" + G + + expect(lockfile).to eq <<~L + GEM + remote: https://gem.repo2/ + specs: + myrack (0.9.1) + myrack_middleware (1.0) + myrack (= 0.9.1) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + myrack_middleware + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "raises a clear error when frozen mode is set and lockfile is missing deps, and does not install any gems" do + lockfile <<-L + GEM + remote: https://gem.repo2/ + specs: + myrack_middleware (1.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + myrack_middleware + + BUNDLED WITH + #{Bundler::VERSION} + L + + install_gemfile <<-G, env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false + source "https://gem.repo2" + gem "myrack_middleware" G - bundle! :install, forgotten_command_line_options(:path => "vendor") - expect(the_bundle).to include_gems "omg 1.0" + expect(err).to include("Bundler found incorrect dependencies in the lockfile for myrack_middleware-1.0") + expect(err).to include("myrack: gemspec specifies = 0.9.1, not in lockfile") + expect(the_bundle).not_to include_gems "myrack_middleware 1.0" + end - # Create a Gemfile.lock that has duplicate GIT sections + it "raises a clear error when frozen mode is set and lockfile is missing entries in CHECKSUMS section, and does not install any gems" do lockfile <<-L GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo2/ specs: + myrack_middleware (1.0) - GIT - remote: #{lib_path("omg")} - revision: #{revision} - branch: master + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + myrack_middleware + + CHECKSUMS + + BUNDLED WITH + #{Bundler::VERSION} + L + + install_gemfile <<-G, env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false + source "https://gem.repo2" + gem "myrack_middleware" + G + + expect(err).to eq <<~L.strip + Your lockfile is missing a CHECKSUMS entry for \"myrack_middleware\", but can't be updated because frozen mode is set + + Run `bundle install` elsewhere and add the updated Gemfile.lock to version control. + L + + expect(the_bundle).not_to include_gems "myrack_middleware 1.0" + end + + it "raises a clear error when frozen mode is set and lockfile has empty checksums in CHECKSUMS section, and does not install any gems" do + lockfile <<-L + GEM + remote: https://gem.repo2/ + specs: + myrack (0.9.1) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + myrack + + CHECKSUMS + myrack (0.9.1) + + BUNDLED WITH + #{Bundler::VERSION} + L + + install_gemfile <<-G, env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false + source "https://gem.repo2" + gem "myrack" + G + + expect(err).to eq <<~L.strip + Your lockfile has an empty CHECKSUMS entry for \"myrack\", but can't be updated because frozen mode is set + + Run `bundle install` elsewhere and add the updated Gemfile.lock to version control. + L + + expect(the_bundle).not_to include_gems "myrack 0.9.1" + end + + it "automatically fixes the lockfile when it's missing deps, they conflict with other locked deps, but conflicts are fixable" do + build_repo4 do + build_gem "other_dep", "0.9" + build_gem "other_dep", "1.0" + + build_gem "myrack", "0.9.1" + + build_gem "myrack_middleware", "1.0" do |s| + s.add_dependency "myrack", "= 0.9.1" + s.add_dependency "other_dep", "= 0.9" + end + end + + lockfile <<~L + GEM + remote: https://gem.repo4/ + specs: + myrack_middleware (1.0) + other_dep (1.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + myrack_middleware + other_dep + + BUNDLED WITH + #{Bundler::VERSION} + L + + install_gemfile <<-G + source "https://gem.repo4" + gem "myrack_middleware" + gem "other_dep" + G + + expect(lockfile).to eq <<~L + GEM + remote: https://gem.repo4/ + specs: + myrack (0.9.1) + myrack_middleware (1.0) + myrack (= 0.9.1) + other_dep (= 0.9) + other_dep (0.9) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + myrack_middleware + other_dep + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "automatically fixes the lockfile when it's missing multiple deps, they conflict with other locked deps, but conflicts are fixable" do + build_repo4 do + build_gem "other_dep", "0.9" + build_gem "other_dep", "1.0" + + build_gem "myrack", "0.9.1" + + build_gem "myrack_middleware", "1.0" do |s| + s.add_dependency "myrack", "= 0.9.1" + end + + build_gem "another_dep_middleware", "1.0" do |s| + s.add_dependency "other_dep", "= 0.9" + end + end + + lockfile <<~L + GEM + remote: https://gem.repo4/ + specs: + myrack_middleware (1.0) + another_dep_middleware (1.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + myrack_middleware + another_dep_middleware + + BUNDLED WITH + #{Bundler::VERSION} + L + + install_gemfile <<-G + source "https://gem.repo4" + gem "myrack_middleware" + gem "another_dep_middleware" + G + + expect(lockfile).to eq <<~L + GEM + remote: https://gem.repo4/ + specs: + another_dep_middleware (1.0) + other_dep (= 0.9) + myrack (0.9.1) + myrack_middleware (1.0) + myrack (= 0.9.1) + other_dep (0.9) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + another_dep_middleware + myrack_middleware + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "raises a resolution error when lockfile is missing deps, they conflict with other locked deps, and conflicts are not fixable" do + build_repo4 do + build_gem "other_dep", "0.9" + build_gem "other_dep", "1.0" + + build_gem "myrack", "0.9.1" + + build_gem "myrack_middleware", "1.0" do |s| + s.add_dependency "myrack", "= 0.9.1" + s.add_dependency "other_dep", "= 0.9" + end + end + + lockfile <<~L + GEM + remote: https://gem.repo4/ + specs: + myrack_middleware (1.0) + other_dep (1.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + myrack_middleware + other_dep + + BUNDLED WITH + #{Bundler::VERSION} + L + + install_gemfile <<-G, raise_on_error: false + source "https://gem.repo4" + gem "myrack_middleware" + gem "other_dep", "1.0" + G + + expect(err).to eq <<~ERROR.strip + Could not find compatible versions + + Because every version of myrack_middleware depends on other_dep = 0.9 + and Gemfile depends on myrack_middleware >= 0, + other_dep = 0.9 is required. + So, because Gemfile depends on other_dep = 1.0, + version solving has failed. + ERROR + 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: https://gem.repo4/ + specs: + + PLATFORMS + ruby + + DEPENDENCIES + direct_dependency + + BUNDLED WITH + #{Bundler::VERSION} + G + + install_gemfile <<-G + source "https://gem.repo4" + + gem "direct_dependency" + G + + expect(lockfile).to eq <<~G + GEM + remote: https://gem.repo4/ + specs: + direct_dependency (4.5.6) + indirect_dependency + indirect_dependency (1.2.3) + + PLATFORMS + #{lockfile_platforms(generic_default_locked_platform || local_platform, defaults: ["ruby"])} + + DEPENDENCIES + direct_dependency + + BUNDLED WITH + #{Bundler::VERSION} + G + end + + it "automatically fixes the lockfile when it's missing deps and the full index is in use" do + lockfile <<-L + GEM + remote: https://gem.repo2/ + specs: + myrack_middleware (1.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + myrack_middleware + + BUNDLED WITH + #{Bundler::VERSION} + L + + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "myrack_middleware" + G + + expect(lockfile).to eq <<~L + GEM + remote: #{file_uri_for(gem_repo2)}/ specs: - omg (1.0) + myrack (0.9.1) + myrack_middleware (1.0) + myrack (= 0.9.1) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + myrack_middleware + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "automatically fixes the lockfile when it includes a gem under the correct GIT section, but also under an incorrect GEM section, with a higher version, and with no explicit Gemfile requirement" do + git = build_git "foo" + + gemfile <<~G + source "https://gem.repo1/" + gem "foo", git: "#{lib_path("foo-1.0")}" + G + + # If the lockfile erroneously lists platform versions of the gem + # that don't match the locked version of the git repo we should remove them. + lockfile <<~L GIT - remote: #{lib_path("omg")} - revision: #{revision} - branch: master + remote: #{lib_path("foo-1.0")} + revision: #{git.ref_for("main")} + specs: + foo (1.0) + + GEM + remote: https://gem.repo1/ specs: - omg (1.0) + foo (1.1-x86_64-linux-gnu) PLATFORMS #{lockfile_platforms} DEPENDENCIES - omg! + foo! BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} L - FileUtils.rm_rf(bundled_app("vendor")) bundle "install" - expect(the_bundle).to include_gems "omg 1.0" - # Confirm that duplicate specs do not appear - expect(File.read(bundled_app("Gemfile.lock"))).to eq(strip_whitespace(<<-L)) + expect(lockfile).to eq <<~L + GIT + remote: #{lib_path("foo-1.0")} + revision: #{git.ref_for("main")} + specs: + foo (1.0) + + GEM + remote: https://gem.repo1/ + specs: + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + foo! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "automatically fixes the lockfile when it includes a gem under the correct GIT section, but also under an incorrect GEM section, with a higher version" do + git = build_git "foo" + + gemfile <<~G + source "https://gem.repo1/" + gem "foo", "= 1.0", git: "#{lib_path("foo-1.0")}" + G + + # If the lockfile erroneously lists platform versions of the gem + # that don't match the locked version of the git repo we should remove them. + + lockfile <<~L + GIT + remote: #{lib_path("foo-1.0")} + revision: #{git.ref_for("main")} + specs: + foo (1.0) + GEM - remote: file:#{gem_repo1}/ + remote: https://gem.repo1/ specs: + foo (1.1-x86_64-linux-gnu) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + foo (= 1.0)! + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "install" + expect(lockfile).to eq <<~L GIT - remote: #{lib_path("omg")} - revision: #{revision} - branch: master + remote: #{lib_path("foo-1.0")} + revision: #{git.ref_for("main")} + specs: + foo (1.0) + + GEM + remote: https://gem.repo1/ specs: - omg (1.0) PLATFORMS #{lockfile_platforms} DEPENDENCIES - omg! + foo (= 1.0)! BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} L end - it "raises a helpful error message when the lockfile is missing deps" do - lockfile <<-L + it "automatically fixes the lockfile when it has incorrect deps, keeping the locked version" do + build_repo4 do + build_gem "net-smtp", "0.5.0" do |s| + s.add_dependency "net-protocol" + end + + build_gem "net-smtp", "0.5.1" do |s| + s.add_dependency "net-protocol" + end + + build_gem "net-protocol", "0.2.2" + end + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + gem "net-smtp" + G + + lockfile <<~L GEM - remote: file:#{gem_repo1}/ + remote: #{file_uri_for(gem_repo4)}/ specs: - rack_middleware (1.0) + net-protocol (0.2.2) + net-smtp (0.5.0) PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack_middleware + net-smtp + + BUNDLED WITH + #{Bundler::VERSION} L - install_gemfile <<-G - source "file:#{gem_repo1}" - gem "rack_middleware" + bundle "install" + + expect(lockfile).to eq <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + net-protocol (0.2.2) + net-smtp (0.5.0) + net-protocol + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + net-smtp + + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "successfully updates the lockfile when a new gem is added in the Gemfile includes a gem that shouldn't be included" do + build_repo4 do + build_gem "logger", "1.7.0" + build_gem "rack", "3.2.0" + build_gem "net-smtp", "0.5.0" + end + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + gem "logger" + gem "net-smtp" + + install_if -> { false } do + gem 'rack', github: 'rack/rack' + end G - expect(out).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.") + lockfile <<~L + GIT + remote: https://github.com/rack/rack.git + revision: 2fface9ac09fc582a81386becd939c987ad33f99 + specs: + rack (3.2.0) + + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + logger (1.7.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + logger + rack! + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "install" + + expect(lockfile).to eq <<~L + GIT + remote: https://github.com/rack/rack.git + revision: 2fface9ac09fc582a81386becd939c987ad33f99 + specs: + rack (3.2.0) + + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + logger (1.7.0) + net-smtp (0.5.0) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + logger + net-smtp + rack! + + BUNDLED WITH + #{Bundler::VERSION} + L + 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 "https://gem.repo4" + gem "minitest-bisect" + G + + # Corrupt lockfile (completely missing path_expander) + lockfile <<~L + GEM + remote: https://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: https://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 "https://gem.repo4" + gem "minitest-bisect" + G + + lockfile <<~L + GEM + remote: https://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 lockfile includes \"minitest-bisect\" but not some of its dependencies") + + expect(lockfile).to eq <<~L + GEM + remote: https://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) - File.utime(time, time, bundled_app("Gemfile.lock")) + File.utime(time, time, bundled_app_lock) end before(:each) do build_repo2 install_gemfile <<-G - source "file://#{gem_repo2}" - gem "rack" + source "https://gem.repo2" + gem "myrack" G set_lockfile_mtime_to_known_value end it "generates Gemfile.lock with \\n line endings" do - expect(File.read(bundled_app("Gemfile.lock"))).not_to match("\r\n") - expect(the_bundle).to include_gems "rack 1.0" + expect(File.read(bundled_app_lock)).not_to match("\r\n") + expect(the_bundle).to include_gems "myrack 1.0" end context "during updates" do it "preserves Gemfile.lock \\n line endings" do - update_repo2 - - expect { bundle "update", :all => true }.to change { File.mtime(bundled_app("Gemfile.lock")) } - expect(File.read(bundled_app("Gemfile.lock"))).not_to match("\r\n") - expect(the_bundle).to include_gems "rack 1.2" + update_repo2 do + build_gem "myrack", "1.2" do |s| + s.executables = "myrackup" + end + end + + 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 "myrack 1.2" end it "preserves Gemfile.lock \\n\\r line endings" do - update_repo2 - win_lock = File.read(bundled_app("Gemfile.lock")).gsub(/\n/, "\r\n") - File.open(bundled_app("Gemfile.lock"), "wb") {|f| f.puts(win_lock) } + skip "needs to be adapted" if Gem.win_platform? + + update_repo2 do + build_gem "myrack", "1.2" do |s| + s.executables = "myrackup" + end + end + + win_lock = File.read(bundled_app_lock).gsub(/\n/, "\r\n") + 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("Gemfile.lock")) } - expect(File.read(bundled_app("Gemfile.lock"))).to match("\r\n") - expect(the_bundle).to include_gems "rack 1.2" + expect { bundle "update", all: true }.to change { File.mtime(bundled_app_lock) } + expect(File.read(bundled_app_lock)).to match("\r\n") + + expect(the_bundle).to include_gems "myrack 1.2" end end @@ -1370,25 +2357,23 @@ RSpec.describe "the lockfile format", :bundler => "2" do it "preserves Gemfile.lock \\n line endings" do expect do ruby <<-RUBY - require 'rubygems' require 'bundler' Bundler.setup RUBY - end.not_to change { File.mtime(bundled_app("Gemfile.lock")) } + end.not_to change { File.mtime(bundled_app_lock) } end it "preserves Gemfile.lock \\n\\r line endings" do - win_lock = File.read(bundled_app("Gemfile.lock")).gsub(/\n/, "\r\n") - File.open(bundled_app("Gemfile.lock"), "wb") {|f| f.puts(win_lock) } + win_lock = File.read(bundled_app_lock).gsub(/\n/, "\r\n") + File.open(bundled_app_lock, "wb") {|f| f.puts(win_lock) } set_lockfile_mtime_to_known_value expect do ruby <<-RUBY - require 'rubygems' require 'bundler' Bundler.setup RUBY - end.not_to change { File.mtime(bundled_app("Gemfile.lock")) } + end.not_to change { File.mtime(bundled_app_lock) } end end end @@ -1396,30 +2381,36 @@ RSpec.describe "the lockfile format", :bundler => "2" do it "refuses to install if Gemfile.lock contains conflict markers" do lockfile <<-L GEM - remote: file://#{gem_repo1}/ + remote: https://gem.repo2// specs: <<<<<<< - rack (1.0.0) + myrack (1.0.0) ======= - rack (1.0.1) + myrack (1.0.1) >>>>>>> PLATFORMS #{lockfile_platforms} DEPENDENCIES - rack + myrack BUNDLED WITH - #{Bundler::VERSION} + #{Bundler::VERSION} L - install_gemfile(<<-G) - source "file://#{gem_repo1}" - gem "rack" + install_gemfile <<-G, raise_on_error: false + source "https://gem.repo2/" + gem "myrack" G - expect(last_command.bundler_err).to match(/your Gemfile.lock contains merge conflicts/i) - expect(last_command.bundler_err).to match(/git checkout HEAD -- Gemfile.lock/i) + expect(err).to match(/your Gemfile.lock contains merge conflicts/i) + expect(err).to match(/git checkout HEAD -- Gemfile.lock/i) + end + + private + + def previous_major(version) + version.split(".").map.with_index {|v, i| i == 0 ? v.to_i - 1 : v }.join(".") end end |
