mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 21:49:06 +02:00

When we need to reset system gems during specs, there's no need to
rebuild bundler, we can copy over the original gem home.
7b4f80747b
654 lines
16 KiB
Ruby
654 lines
16 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe "bundle check" do
|
|
it "returns success when the Gemfile is satisfied" do
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "rails"
|
|
G
|
|
|
|
bundle :check
|
|
expect(out).to include("The Gemfile's dependencies are satisfied")
|
|
end
|
|
|
|
it "works with the --gemfile flag when not in the directory" do
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "rails"
|
|
G
|
|
|
|
bundle "check --gemfile bundled_app/Gemfile", dir: tmp
|
|
expect(out).to include("The Gemfile's dependencies are satisfied")
|
|
end
|
|
|
|
it "creates a Gemfile.lock by default if one does not exist" do
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "rails"
|
|
G
|
|
|
|
FileUtils.rm(bundled_app_lock)
|
|
|
|
bundle "check"
|
|
|
|
expect(bundled_app_lock).to exist
|
|
end
|
|
|
|
it "does not create a Gemfile.lock if --dry-run was passed" do
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "rails"
|
|
G
|
|
|
|
FileUtils.rm(bundled_app_lock)
|
|
|
|
bundle "check --dry-run"
|
|
|
|
expect(bundled_app_lock).not_to exist
|
|
end
|
|
|
|
it "prints an error that shows missing gems" do
|
|
system_gems ["rails-2.3.2"], path: default_bundle_path
|
|
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "rails"
|
|
G
|
|
|
|
bundle :check, raise_on_error: false
|
|
expect(err).to include("The following gems are missing")
|
|
expect(err).to include(" * rake (#{rake_version})")
|
|
expect(err).to include(" * actionpack (2.3.2)")
|
|
expect(err).to include(" * activerecord (2.3.2)")
|
|
expect(err).to include(" * actionmailer (2.3.2)")
|
|
expect(err).to include(" * activeresource (2.3.2)")
|
|
expect(err).to include(" * activesupport (2.3.2)")
|
|
expect(err).to include("Install missing gems with `bundle install`")
|
|
end
|
|
|
|
it "prints an error that shows missing gems if a Gemfile.lock does not exist and a toplevel dependency is missing" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "rails"
|
|
G
|
|
|
|
bundle :check, raise_on_error: false
|
|
expect(exitstatus).to be > 0
|
|
expect(err).to include("The following gems are missing")
|
|
expect(err).to include(" * rails (2.3.2)")
|
|
expect(err).to include(" * rake (#{rake_version})")
|
|
expect(err).to include(" * actionpack (2.3.2)")
|
|
expect(err).to include(" * activerecord (2.3.2)")
|
|
expect(err).to include(" * actionmailer (2.3.2)")
|
|
expect(err).to include(" * activeresource (2.3.2)")
|
|
expect(err).to include(" * activesupport (2.3.2)")
|
|
expect(err).to include("Install missing gems with `bundle install`")
|
|
end
|
|
|
|
it "prints a generic error if gem git source is not checked out" do
|
|
build_git "foo", path: lib_path("foo")
|
|
|
|
bundle "config path vendor/bundle"
|
|
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "foo", git: "#{lib_path("foo")}"
|
|
G
|
|
|
|
FileUtils.rm_r bundled_app("vendor/bundle")
|
|
bundle :check, raise_on_error: false
|
|
expect(exitstatus).to eq 1
|
|
expect(err).to include("Bundler can't satisfy your Gemfile's dependencies.")
|
|
end
|
|
|
|
it "prints a generic message if you changed your lockfile" do
|
|
build_repo2 do
|
|
build_gem "rails_pinned_to_old_activesupport" do |s|
|
|
s.add_dependency "activesupport", "= 1.2.3"
|
|
end
|
|
end
|
|
|
|
install_gemfile <<-G
|
|
source "https://gem.repo2"
|
|
gem 'rails'
|
|
G
|
|
|
|
gemfile <<-G
|
|
source "https://gem.repo2"
|
|
gem "rails"
|
|
gem "rails_pinned_to_old_activesupport"
|
|
G
|
|
|
|
bundle :check, raise_on_error: false
|
|
expect(err).to include("Bundler can't satisfy your Gemfile's dependencies.")
|
|
end
|
|
|
|
it "remembers --without option from install" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
group :foo do
|
|
gem "myrack"
|
|
end
|
|
G
|
|
|
|
bundle "install --without foo"
|
|
bundle "check"
|
|
expect(out).to include("The Gemfile's dependencies are satisfied")
|
|
end
|
|
|
|
it "uses the without setting" do
|
|
bundle "config set without foo"
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
group :foo do
|
|
gem "myrack"
|
|
end
|
|
G
|
|
|
|
bundle "check"
|
|
expect(out).to include("The Gemfile's dependencies are satisfied")
|
|
end
|
|
|
|
it "ensures that gems are actually installed and not just cached" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "myrack", :group => :foo
|
|
G
|
|
|
|
bundle "config set --local without foo"
|
|
bundle :install
|
|
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "myrack"
|
|
G
|
|
|
|
bundle "check", raise_on_error: false
|
|
expect(err).to include("* myrack (1.0.0)")
|
|
expect(exitstatus).to eq(1)
|
|
end
|
|
|
|
it "ensures that gems are actually installed and not just cached in applications' cache" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "myrack"
|
|
G
|
|
|
|
bundle "config set --local path vendor/bundle"
|
|
bundle :cache
|
|
|
|
gem_command "uninstall myrack", env: { "GEM_HOME" => vendored_gems.to_s }
|
|
|
|
bundle "check", raise_on_error: false
|
|
expect(err).to include("* myrack (1.0.0)")
|
|
expect(exitstatus).to eq(1)
|
|
end
|
|
|
|
it "ignores missing gems restricted to other platforms" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "myrack"
|
|
platforms :#{not_local_tag} do
|
|
gem "activesupport"
|
|
end
|
|
G
|
|
|
|
system_gems "myrack-1.0.0", path: default_bundle_path
|
|
|
|
lockfile <<-G
|
|
GEM
|
|
remote: https://gem.repo1/
|
|
specs:
|
|
activesupport (2.3.5)
|
|
myrack (1.0.0)
|
|
|
|
PLATFORMS
|
|
#{generic_local_platform}
|
|
#{not_local}
|
|
|
|
DEPENDENCIES
|
|
myrack
|
|
activesupport
|
|
G
|
|
|
|
bundle :check
|
|
expect(out).to include("The Gemfile's dependencies are satisfied")
|
|
end
|
|
|
|
it "works with env conditionals" do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "myrack"
|
|
env :NOT_GOING_TO_BE_SET do
|
|
gem "activesupport"
|
|
end
|
|
G
|
|
|
|
system_gems "myrack-1.0.0", path: default_bundle_path
|
|
|
|
lockfile <<-G
|
|
GEM
|
|
remote: https://gem.repo1/
|
|
specs:
|
|
activesupport (2.3.5)
|
|
myrack (1.0.0)
|
|
|
|
PLATFORMS
|
|
#{generic_local_platform}
|
|
#{not_local}
|
|
|
|
DEPENDENCIES
|
|
myrack
|
|
activesupport
|
|
G
|
|
|
|
bundle :check
|
|
expect(out).to include("The Gemfile's dependencies are satisfied")
|
|
end
|
|
|
|
it "outputs an error when the default Gemfile is not found" do
|
|
bundle :check, raise_on_error: false
|
|
expect(exitstatus).to eq(10)
|
|
expect(err).to include("Could not locate Gemfile")
|
|
end
|
|
|
|
it "does not output fatal error message" do
|
|
bundle :check, raise_on_error: false
|
|
expect(exitstatus).to eq(10)
|
|
expect(err).not_to include("Unfortunately, a fatal error has occurred. ")
|
|
end
|
|
|
|
it "fails when there's no lockfile and frozen is set" do
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "foo"
|
|
G
|
|
|
|
bundle "config set --local deployment true"
|
|
bundle "install"
|
|
FileUtils.rm(bundled_app_lock)
|
|
|
|
bundle :check, raise_on_error: false
|
|
expect(last_command).to be_failure
|
|
end
|
|
|
|
context "--path" do
|
|
context "after installing gems in the proper directory" do
|
|
before do
|
|
gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "rails"
|
|
G
|
|
bundle "install --path vendor/bundle"
|
|
|
|
FileUtils.rm_r(bundled_app(".bundle"))
|
|
end
|
|
|
|
it "returns success" do
|
|
bundle "check --path vendor/bundle"
|
|
expect(out).to include("The Gemfile's dependencies are satisfied")
|
|
end
|
|
|
|
it "should write to .bundle/config" do
|
|
bundle "check --path vendor/bundle"
|
|
bundle "check"
|
|
end
|
|
end
|
|
|
|
context "after installing gems on a different directory" do
|
|
before do
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "rails"
|
|
G
|
|
|
|
bundle "check --path vendor/bundle", raise_on_error: false
|
|
end
|
|
|
|
it "returns false" do
|
|
expect(exitstatus).to eq(1)
|
|
expect(err).to match(/The following gems are missing/)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "when locked" do
|
|
before :each do
|
|
system_gems "myrack-1.0.0"
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "myrack", "1.0"
|
|
G
|
|
end
|
|
|
|
it "returns success when the Gemfile is satisfied" do
|
|
bundle :install
|
|
bundle :check
|
|
expect(out).to include("The Gemfile's dependencies are satisfied")
|
|
end
|
|
|
|
it "shows what is missing with the current Gemfile if it is not satisfied" do
|
|
FileUtils.rm_r default_bundle_path
|
|
default_system_gems
|
|
bundle :check, raise_on_error: false
|
|
expect(err).to match(/The following gems are missing/)
|
|
expect(err).to include("* myrack (1.0")
|
|
end
|
|
end
|
|
|
|
describe "when locked with multiple dependents with different requirements" do
|
|
before :each do
|
|
build_repo4 do
|
|
build_gem "depends_on_myrack" do |s|
|
|
s.add_dependency "myrack", ">= 1.0"
|
|
end
|
|
build_gem "also_depends_on_myrack" do |s|
|
|
s.add_dependency "myrack", "~> 1.0"
|
|
end
|
|
build_gem "myrack"
|
|
end
|
|
|
|
gemfile <<-G
|
|
source "https://gem.repo4"
|
|
gem "depends_on_myrack"
|
|
gem "also_depends_on_myrack"
|
|
G
|
|
|
|
bundle "lock"
|
|
end
|
|
|
|
it "shows what is missing with the current Gemfile without duplications" do
|
|
bundle :check, raise_on_error: false
|
|
expect(err).to match(/The following gems are missing/)
|
|
expect(err).to include("* myrack (1.0").once
|
|
end
|
|
end
|
|
|
|
describe "when locked under multiple platforms" do
|
|
before :each do
|
|
build_repo4 do
|
|
build_gem "myrack"
|
|
end
|
|
|
|
gemfile <<-G
|
|
source "https://gem.repo4"
|
|
gem "myrack"
|
|
G
|
|
|
|
lockfile <<-L
|
|
GEM
|
|
remote: https://gem.repo4/
|
|
specs:
|
|
myrack (1.0)
|
|
|
|
PLATFORMS
|
|
ruby
|
|
#{local_platform}
|
|
|
|
DEPENDENCIES
|
|
myrack
|
|
|
|
BUNDLED WITH
|
|
#{Bundler::VERSION}
|
|
L
|
|
end
|
|
|
|
it "shows what is missing with the current Gemfile without duplications" do
|
|
bundle :check, raise_on_error: false
|
|
expect(err).to match(/The following gems are missing/)
|
|
expect(err).to include("* myrack (1.0").once
|
|
end
|
|
end
|
|
|
|
describe "when using only scoped rubygems sources" do
|
|
before do
|
|
gemfile <<~G
|
|
source "https://gem.repo2"
|
|
source "https://gem.repo1" do
|
|
gem "myrack"
|
|
end
|
|
G
|
|
end
|
|
|
|
it "returns success when the Gemfile is satisfied" do
|
|
system_gems "myrack-1.0.0", path: default_bundle_path
|
|
bundle :check, artifice: "compact_index"
|
|
expect(out).to include("The Gemfile's dependencies are satisfied")
|
|
end
|
|
end
|
|
|
|
describe "when using only scoped rubygems sources with indirect dependencies" do
|
|
before do
|
|
build_repo4 do
|
|
build_gem "depends_on_myrack" do |s|
|
|
s.add_dependency "myrack"
|
|
end
|
|
|
|
build_gem "myrack"
|
|
end
|
|
|
|
gemfile <<~G
|
|
source "https://gem.repo1"
|
|
source "https://gem.repo4" do
|
|
gem "depends_on_myrack"
|
|
end
|
|
G
|
|
end
|
|
|
|
it "returns success when the Gemfile is satisfied and generates a correct lockfile" do
|
|
system_gems "depends_on_myrack-1.0", "myrack-1.0", gem_repo: gem_repo4, path: default_bundle_path
|
|
bundle :check, artifice: "compact_index"
|
|
|
|
checksums = checksums_section_when_enabled do |c|
|
|
c.checksum gem_repo4, "depends_on_myrack", "1.0"
|
|
c.checksum gem_repo4, "myrack", "1.0"
|
|
end
|
|
|
|
expect(out).to include("The Gemfile's dependencies are satisfied")
|
|
expect(lockfile).to eq <<~L
|
|
GEM
|
|
remote: https://gem.repo1/
|
|
specs:
|
|
|
|
GEM
|
|
remote: https://gem.repo4/
|
|
specs:
|
|
depends_on_myrack (1.0)
|
|
myrack
|
|
myrack (1.0)
|
|
|
|
PLATFORMS
|
|
#{lockfile_platforms}
|
|
|
|
DEPENDENCIES
|
|
depends_on_myrack!
|
|
#{checksums}
|
|
BUNDLED WITH
|
|
#{Bundler::VERSION}
|
|
L
|
|
end
|
|
end
|
|
|
|
context "with gemspec directive and scoped sources" do
|
|
before do
|
|
build_repo4 do
|
|
build_gem "awesome_print"
|
|
end
|
|
|
|
build_repo2 do
|
|
build_gem "dex-dispatch-engine"
|
|
end
|
|
|
|
build_lib("bundle-check-issue", path: tmp("bundle-check-issue")) do |s|
|
|
s.write "Gemfile", <<-G
|
|
source "https://localgemserver.test"
|
|
|
|
gemspec
|
|
|
|
source "https://localgemserver.test/extra" do
|
|
gem "dex-dispatch-engine"
|
|
end
|
|
G
|
|
|
|
s.add_dependency "awesome_print"
|
|
end
|
|
|
|
bundle "install", artifice: "compact_index_extra", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }, dir: tmp("bundle-check-issue")
|
|
end
|
|
|
|
it "does not corrupt lockfile when changing version" do
|
|
version_file = tmp("bundle-check-issue/bundle-check-issue.gemspec")
|
|
File.write(version_file, File.read(version_file).gsub(/s\.version = .+/, "s.version = '9999'"))
|
|
|
|
bundle "check --verbose", dir: tmp("bundle-check-issue")
|
|
|
|
lockfile = File.read(tmp("bundle-check-issue/Gemfile.lock"))
|
|
|
|
checksums = checksums_section_when_enabled(lockfile) do |c|
|
|
c.checksum gem_repo4, "awesome_print", "1.0"
|
|
c.no_checksum "bundle-check-issue", "9999"
|
|
c.checksum gem_repo2, "dex-dispatch-engine", "1.0"
|
|
end
|
|
|
|
expect(lockfile).to eq <<~L
|
|
PATH
|
|
remote: .
|
|
specs:
|
|
bundle-check-issue (9999)
|
|
awesome_print
|
|
|
|
GEM
|
|
remote: https://localgemserver.test/
|
|
specs:
|
|
awesome_print (1.0)
|
|
|
|
GEM
|
|
remote: https://localgemserver.test/extra/
|
|
specs:
|
|
dex-dispatch-engine (1.0)
|
|
|
|
PLATFORMS
|
|
#{lockfile_platforms}
|
|
|
|
DEPENDENCIES
|
|
bundle-check-issue!
|
|
dex-dispatch-engine!
|
|
#{checksums}
|
|
BUNDLED WITH
|
|
#{Bundler::VERSION}
|
|
L
|
|
end
|
|
end
|
|
|
|
context "with scoped and unscoped sources" do
|
|
it "does not corrupt lockfile" do
|
|
build_repo2 do
|
|
build_gem "foo"
|
|
build_gem "wadus"
|
|
build_gem("baz") {|s| s.add_dependency "wadus" }
|
|
end
|
|
|
|
build_repo4 do
|
|
build_gem "bar"
|
|
end
|
|
|
|
bundle "config set path.system true"
|
|
|
|
# Add all gems to ensure all gems are installed so that a bundle check
|
|
# would be successful
|
|
install_gemfile(<<-G, artifice: "compact_index_extra")
|
|
source "https://gem.repo2"
|
|
|
|
source "https://gem.repo4" do
|
|
gem "bar"
|
|
end
|
|
|
|
gem "foo"
|
|
gem "baz"
|
|
G
|
|
|
|
original_lockfile = lockfile
|
|
|
|
# Remove "baz" gem from the Gemfile, and bundle install again to generate
|
|
# a functional lockfile with no "baz" dependency or "wadus" transitive
|
|
# dependency
|
|
install_gemfile(<<-G, artifice: "compact_index_extra")
|
|
source "https://gem.repo2"
|
|
|
|
source "https://gem.repo4" do
|
|
gem "bar"
|
|
end
|
|
|
|
gem "foo"
|
|
G
|
|
|
|
# Add back "baz" gem back to the Gemfile, but _crucially_ we do not perform a
|
|
# bundle install
|
|
gemfile(gemfile + 'gem "baz"')
|
|
|
|
bundle :check, verbose: true
|
|
|
|
# Bundle check should succeed and restore the lockfile to its original
|
|
# state
|
|
expect(lockfile).to eq(original_lockfile)
|
|
end
|
|
end
|
|
|
|
describe "BUNDLED WITH" do
|
|
def lock_with(bundler_version = nil)
|
|
lock = <<~L
|
|
GEM
|
|
remote: https://gem.repo1/
|
|
specs:
|
|
myrack (1.0.0)
|
|
|
|
PLATFORMS
|
|
#{lockfile_platforms}
|
|
|
|
DEPENDENCIES
|
|
myrack
|
|
L
|
|
|
|
if bundler_version
|
|
lock += "\nBUNDLED WITH\n #{bundler_version}\n"
|
|
end
|
|
|
|
lock
|
|
end
|
|
|
|
before do
|
|
bundle "config set --local path vendor/bundle"
|
|
|
|
install_gemfile <<-G
|
|
source "https://gem.repo1"
|
|
gem "myrack"
|
|
G
|
|
end
|
|
|
|
context "is not present" do
|
|
it "does not change the lock" do
|
|
lockfile lock_with(nil)
|
|
bundle :check
|
|
expect(lockfile).to eq lock_with(nil)
|
|
end
|
|
end
|
|
|
|
context "is newer" do
|
|
it "does not change the lock and does not warn" do
|
|
lockfile lock_with(Bundler::VERSION.succ)
|
|
bundle :check
|
|
expect(err).to be_empty
|
|
expect(lockfile).to eq lock_with(Bundler::VERSION.succ)
|
|
end
|
|
end
|
|
|
|
context "is older" do
|
|
it "does not change the lock" do
|
|
system_gems "bundler-1.18.0"
|
|
lockfile lock_with("1.18.0")
|
|
bundle :check
|
|
expect(lockfile).to eq lock_with("1.18.0")
|
|
end
|
|
end
|
|
end
|
|
end
|