ruby/spec/bundler/lock/lockfile_spec.rb
David Rodríguez 90085f62fb [rubygems/rubygems] Simulate Bundler 4 in a better way
Overriding the version constant feels too magic and creates a set of
problems. For example, Bundler will lock the simulated version, and that
can cause issues when the lockfile is used under an environment not
simulating Bundler 4 (it will try to auto-install and auto-switch to a
version that does not exist).

On top of that, it can only be configured with an ENV variable which is
not too flexible.

This commit takes a different approach of using a setting, which is
configurable through ENV or `bundle config`, and pass the simulated
version to `Bundler::FeatureFlag`. The real version is still the one set
by `VERSION`, but anything that `Bundler::FeatureFlag` controls will use
the logic of the "simulated version".

In particular, all feature flags and deprecation messages will respect
the simulated version, and this is exactly the set of functionality that
we want users to be able to easily try before releasing it.

8129402193
2025-06-26 08:06:48 +09:00

2314 lines
50 KiB
Ruby

# frozen_string_literal: 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 "https://gem.repo2"
gem "myrack"
G
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}
G
end
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
revision: 8a2271f
specs:
GEM
remote: https://gem.repo2/
specs:
myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
omg!
myrack
BUNDLED WITH
1.8.2
L
install_gemfile <<-G, verbose: true, env: { "BUNDLER_VERSION" => Bundler::VERSION }
source "https://gem.repo2"
gem "myrack"
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: https://gem.repo2/
specs:
myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack
BUNDLED WITH
#{Bundler::VERSION}
G
end
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: https://gem.repo4/
specs:
myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack
BUNDLED WITH
#{version}
L
install_gemfile <<-G, verbose: true
source "https://gem.repo4"
gem "myrack"
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: https://gem.repo4/
specs:
myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack
BUNDLED WITH
#{version}
G
end
it "adds the BUNDLED WITH section if not present" do
lockfile <<-L
GEM
remote: https://gem.repo2/
specs:
myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack
L
install_gemfile <<-G
source "https://gem.repo2"
gem "myrack", "> 0"
G
expect(lockfile).to eq <<~G
GEM
remote: https://gem.repo2/
specs:
myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack (> 0)
BUNDLED WITH
#{Bundler::VERSION}
G
end
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: https://gem.repo2/
specs:
myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack
BUNDLED WITH
#{older_major}
L
install_gemfile <<-G, env: { "BUNDLER_VERSION" => Bundler::VERSION }
source "https://gem.repo2/"
gem "myrack"
G
expect(err).to be_empty
expect(lockfile).to eq <<~G
GEM
remote: https://gem.repo2/
specs:
myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack
BUNDLED WITH
#{current_version}
G
end
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: https://gem.repo2/
specs:
myrack (1.0.0)
myrack-obama (1.0)
myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack-obama
#{checksums}
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 "https://gem.repo2/"
gem "myrack-obama", ">= 1.0"
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: https://gem.repo2/
specs:
myrack (1.0.0)
myrack-obama (1.0)
myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack-obama (>= 1.0)
#{checksums}
BUNDLED WITH
#{Bundler::VERSION}
G
end
it "generates a lockfile without credentials" do
bundle "config set https://localgemserver.test/ user:pass"
install_gemfile(<<-G, artifice: "endpoint_strict_basic_authentication", quiet: true)
source "https://gem.repo1"
source "https://localgemserver.test/" do
end
source "https://user:pass@othergemserver.test/" do
gem "myrack-obama", ">= 1.0"
end
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: https://gem.repo1/
specs:
GEM
remote: https://localgemserver.test/
specs:
GEM
remote: https://othergemserver.test/
specs:
myrack (1.0.0)
myrack-obama (1.0)
myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack-obama (>= 1.0)!
#{checksums}
BUNDLED WITH
#{Bundler::VERSION}
G
end
it "does not add credentials to lockfile when it does not have them already" do
bundle "config set http://localgemserver.test/ user:pass"
gemfile <<~G
source "https://gem.repo1"
source "http://localgemserver.test/" do
end
source "http://user:pass@othergemserver.test/" do
gem "myrack-obama", ">= 1.0"
end
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
lockfile_without_credentials = <<~L
GEM
remote: http://localgemserver.test/
specs:
GEM
remote: http://othergemserver.test/
specs:
myrack (1.0.0)
myrack-obama (1.0)
myrack
GEM
remote: https://gem.repo1/
specs:
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack-obama (>= 1.0)!
#{checksums}
BUNDLED WITH
#{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 "keeps credentials in lockfile if already there" do
bundle "config set http://localgemserver.test/ user:pass"
gemfile <<~G
source "https://gem.repo1"
source "http://localgemserver.test/" do
end
source "http://user:pass@othergemserver.test/" do
gem "myrack-obama", ">= 1.0"
end
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
lockfile_with_credentials = <<~L
GEM
remote: http://localgemserver.test/
specs:
GEM
remote: http://user:pass@othergemserver.test/
specs:
myrack (1.0.0)
myrack-obama (1.0)
myrack
GEM
remote: https://gem.repo1/
specs:
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack-obama (>= 1.0)!
#{checksums}
BUNDLED WITH
#{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 "https://gem.repo2/"
gem "net-sftp"
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: https://gem.repo2/
specs:
net-sftp (1.1.1)
net-ssh (>= 1.0.0, < 1.99.0)
net-ssh (1.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
net-sftp
#{checksums}
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
source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
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("main")}
specs:
foo (1.0)
GEM
remote: https://gem.repo1/
specs:
PLATFORMS
#{lockfile_platforms}
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")
gemfile <<-G
source "https://gem.repo2/"
platforms :#{not_local_tag} do
gem "omg", :path => "#{lib_path("omg")}"
end
gem "myrack"
G
lockfile <<-L
GIT
remote: git://github.com/nex3/haml.git
revision: 8a2271f
specs:
GEM
remote: https://gem.repo2//
specs:
myrack (1.0.0)
PLATFORMS
#{not_local}
DEPENDENCIES
omg!
myrack
BUNDLED WITH
#{Bundler::VERSION}
L
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
expect(lockfile).to eq <<~G
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!
#{checksums}
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"
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
expect(lockfile).to eq <<~G
GIT
remote: #{lib_path("foo-1.0")}
revision: #{git.ref_for("omg")}
branch: omg
specs:
foo (1.0)
GEM
remote: https://gem.repo1/
specs:
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
foo!
#{checksums}
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"
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
expect(lockfile).to eq <<~G
GIT
remote: #{lib_path("foo-1.0")}
revision: #{git.ref_for("omg")}
tag: omg
specs:
foo (1.0)
GEM
remote: https://gem.repo1/
specs:
PLATFORMS
#{lockfile_platforms}
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: @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
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}
G
end
it "serializes pinned path sources to the lockfile even when packaging" do
build_lib "foo"
install_gemfile <<-G
source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo-1.0")}"
G
checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
end
bundle "config set cache_all true"
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}
G
end
it "sorts serialized sources by type" 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 "https://gem.repo2/"
gem "myrack"
gem "foo", :path => "#{lib_path("foo-1.0")}"
gem "bar", :git => "#{lib_path("bar-1.0")}"
G
expect(lockfile).to eq <<~G
GIT
remote: #{lib_path("bar-1.0")}
revision: #{bar.ref_for("main")}
specs:
bar (1.0)
PATH
remote: #{lib_path("foo-1.0")}
specs:
foo (1.0)
GEM
remote: https://gem.repo2/
specs:
myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
bar!
foo!
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}
G
end
it "lists gems alphabetically" do
install_gemfile <<-G
source "https://gem.repo2/"
gem "thin"
gem "actionpack"
gem "myrack-obama"
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: https://gem.repo2/
specs:
actionpack (2.3.2)
activesupport (= 2.3.2)
activesupport (2.3.2)
myrack (1.0.0)
myrack-obama (1.0)
myrack
thin (1.0)
myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
actionpack
myrack-obama
thin
#{checksums}
BUNDLED WITH
#{Bundler::VERSION}
G
end
it "orders dependencies' dependencies in alphabetical order" do
install_gemfile <<-G
source "https://gem.repo2/"
gem "rails"
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: https://gem.repo2/
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 (= #{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 "https://gem.repo2"
gem 'double_deps'
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: https://gem.repo2/
specs:
double_deps (1.0)
net-ssh
net-ssh (>= 1.0.0)
net-ssh (1.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
double_deps
#{checksums}
BUNDLED WITH
#{Bundler::VERSION}
G
end
it "does not add the :require option to the lockfile" do
install_gemfile <<-G
source "https://gem.repo2/"
gem "myrack-obama", ">= 1.0", :require => "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: https://gem.repo2/
specs:
myrack (1.0.0)
myrack-obama (1.0)
myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack-obama (>= 1.0)
#{checksums}
BUNDLED WITH
#{Bundler::VERSION}
G
end
it "does not add the :group option to the lockfile" do
install_gemfile <<-G
source "https://gem.repo2/"
gem "myrack-obama", ">= 1.0", :group => :test
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: https://gem.repo2/
specs:
myrack (1.0.0)
myrack-obama (1.0)
myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack-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")
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
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}
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"))
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
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}
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
source "https://gem.repo1"
path File.expand_path("foo", __dir__) do
gem "foo"
end
G
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}
G
end
it "stores relative paths when the path is provided for gemspec" do
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
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}
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: https://gem.repo2/
specs:
myrack (1.0.0)
PLATFORMS
java
DEPENDENCIES
myrack
#{checksums}
BUNDLED WITH
#{Bundler::VERSION}
G
install_gemfile <<-G
source "https://gem.repo2/"
gem "myrack"
G
checksums.checksum(gem_repo2, "myrack", "1.0.0")
expect(lockfile).to eq <<~G
GEM
remote: https://gem.repo2/
specs:
myrack (1.0.0)
PLATFORMS
#{lockfile_platforms("java", local_platform, defaults: [])}
DEPENDENCIES
myrack
#{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 "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" do
install_gemfile <<-G
source "https://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
expect(lockfile).to eq <<~G
GEM
remote: https://gem.repo2/
specs:
platform_specific (1.0-universal-java-16)
PLATFORMS
universal-java-16
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 "https://gem.repo2/"
gem "myrack"
G
install_gemfile <<-G
source "https://gem.repo2/"
gem "myrack"
gem "activesupport"
G
expect(lockfile).to eq <<~G
GEM
remote: https://gem.repo2/
specs:
activesupport (2.3.5)
myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
activesupport
myrack
#{checksums}
BUNDLED WITH
#{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 "https://gem.repo2/"
gem "myrack"
gem "myrack"
G
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}
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 "https://gem.repo2/"
gem "myrack", "1.0"
gem "myrack", "1.0"
G
expect(lockfile).to eq <<~G
GEM
remote: https://gem.repo2/
specs:
myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack (= 1.0)
#{checksums}
BUNDLED WITH
#{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 "https://gem.repo2/"
gem "myrack", "1.0", :group => :one
gem "myrack", "1.0", :group => :two
G
expect(lockfile).to eq <<~G
GEM
remote: https://gem.repo2/
specs:
myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack (= 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
source "https://gem.repo2/"
gem "myrack", "1.0"
gem "myrack", "1.1"
G
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, raise_on_error: false
source "https://gem.repo2/"
gem "myrack"
gem "myrack", :git => "git://hubz.com"
G
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 "https://gem.repo2/"
gem "myrack", "> 0.9", "< 1.0"
G
expect(lockfile).to eq <<~G
GEM
remote: https://gem.repo2/
specs:
myrack (0.9.1)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack (> 0.9, < 1.0)
#{checksums}
BUNDLED WITH
#{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 "https://gem.repo2/"
ruby '#{Gem.ruby_version}'
gem "myrack", "> 0.9", "< 1.0"
G
expect(lockfile).to eq <<~G
GEM
remote: https://gem.repo2/
specs:
myrack (0.9.1)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack (> 0.9, < 1.0)
#{checksums}
RUBY VERSION
#{Bundler::RubyVersion.system}
BUNDLED WITH
#{Bundler::VERSION}
G
end
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}
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
expect(err).to eq("Bundler found incorrect dependencies in the lockfile for myrack_middleware-1.0")
expect(the_bundle).not_to include_gems "myrack_middleware 1.0"
end
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: https://gem.repo2/
specs:
myrack_middleware (1.0)
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 "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:
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("foo-1.0")}
revision: #{git.ref_for("main")}
specs:
foo (1.0)
GEM
remote: https://gem.repo1/
specs:
foo (1.1-x86_64-linux-gnu)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
foo!
BUNDLED WITH
#{Bundler::VERSION}
L
bundle "install"
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: 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("foo-1.0")}
revision: #{git.ref_for("main")}
specs:
foo (1.0)
GEM
remote: https://gem.repo1/
specs:
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
foo (= 1.0)!
BUNDLED WITH
#{Bundler::VERSION}
L
end
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_uri_for(gem_repo4)}/
specs:
net-protocol (0.2.2)
net-smtp (0.5.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
net-smtp
BUNDLED WITH
#{Bundler::VERSION}
L
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
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_lock)
end
before(:each) do
build_repo2
install_gemfile <<-G
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_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 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
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_lock) }
expect(File.read(bundled_app_lock)).to match("\r\n")
expect(the_bundle).to include_gems "myrack 1.2"
end
end
context "when nothing changes" do
it "preserves Gemfile.lock \\n line endings" do
expect do
ruby <<-RUBY
require 'bundler'
Bundler.setup
RUBY
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_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 'bundler'
Bundler.setup
RUBY
end.not_to change { File.mtime(bundled_app_lock) }
end
end
end
it "refuses to install if Gemfile.lock contains conflict markers" do
lockfile <<-L
GEM
remote: https://gem.repo2//
specs:
<<<<<<<
myrack (1.0.0)
=======
myrack (1.0.1)
>>>>>>>
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
myrack
BUNDLED WITH
#{Bundler::VERSION}
L
install_gemfile <<-G, raise_on_error: false
source "https://gem.repo2/"
gem "myrack"
G
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