Merge RubyGems/Bundler 4.0.11

This commit is contained in:
Hiroshi SHIBATA authored and Takashi Kokubun committed 2026-06-03 16:56:21 -07:00
1 parent 9ad5e20f41
commit 56058d238b
60 files changed
+232 -117

No files matched your search

+1 -1
View File
@@ -288,7 +288,7 @@ module Bundler
open_editor(options["edit"], target.join("#{name}.gemspec")) if options[:edit]
Bundler.ui.info "\nGem '#{name}' was successfully created. " \
"For more information on making a RubyGem visit https://bundler.io/guides/creating_gem.html"
"For more information on making a RubyGem visit https://guides.rubygems.org/make-your-own-gem/"
end
private
+2
View File
@@ -988,6 +988,8 @@ module Bundler
end
end
sources.metadata_source.checksum_store.merge!(@locked_gems.metadata_source.checksum_store) if @locked_gems
changes
end
+11 -19
View File
@@ -6,7 +6,7 @@ require_relative "gem_installer"
module Bundler
class ParallelInstaller
class SpecInstallation
attr_accessor :spec, :name, :full_name, :post_install_message, :state, :error
attr_accessor :spec, :name, :full_name, :post_install_message, :state, :error, :dependencies
def initialize(spec)
@spec = spec
@name = spec.name
@@ -46,25 +46,11 @@ module Bundler
!post_install_message.empty?
end
def ignorable_dependency?(dep)
dep.type == :development || dep.name == @name
end
# Checks installed dependencies against spec's dependencies to make
# sure needed dependencies have been installed.
# Recursively checks that all dependencies (direct and transitive) have been installed.
def dependencies_installed?(installed_specs)
dependencies.all? {|d| installed_specs.include? d.name }
end
# Represents only the non-development dependencies, the ones that are
# itself and are in the total list.
def dependencies
@dependencies ||= all_dependencies.reject {|dep| ignorable_dependency? dep }
end
# Represents all dependencies
def all_dependencies
@spec.dependencies
dependencies.all? do |dep|
installed_specs.include?(dep.name) && dep.dependencies_installed?(installed_specs)
end
end
def to_s
@@ -85,6 +71,12 @@ module Bundler
@force = force
@local = local
@specs = all_specs.map {|s| SpecInstallation.new(s) }
specs_by_name = @specs.to_h {|s| [s.name, s] }
@specs.each do |spec_install|
spec_install.dependencies = spec_install.spec.dependencies.filter_map do |dep|
specs_by_name[dep.name] unless dep.type == :development || dep.name == spec_install.name
end
end
@specs.each do |spec_install|
spec_install.state = :installed if skip.include?(spec_install.name)
end if skip
+16 -1
View File
@@ -71,7 +71,8 @@ module Bundler
checksums = definition.resolve.map do |spec|
spec.source.checksum_store.to_lock(spec)
end
add_section("CHECKSUMS", checksums)
add_section("CHECKSUMS", checksums + bundler_checksum)
end
def add_locked_ruby_version
@@ -100,5 +101,19 @@ module Bundler
raise ArgumentError, "#{value.inspect} can't be serialized in a lockfile"
end
end
def bundler_checksum
return [] if Bundler.gem_version.to_s.end_with?(".dev") || ENV["SKIP_BUNDLER_CHECKSUM"]
bundler_spec = definition.sources.metadata_source.specs.search(["bundler", Bundler.gem_version]).last
return [] unless File.exist?(bundler_spec.cache_file)
require "rubygems/package"
package = Gem::Package.new(bundler_spec.cache_file)
definition.sources.metadata_source.checksum_store.register(bundler_spec, Checksum.from_gem_package(package))
[definition.sources.metadata_source.checksum_store.to_lock(bundler_spec)]
end
end
end
+8 -1
View File
@@ -28,6 +28,7 @@ module Bundler
attr_reader(
:sources,
:metadata_source,
:dependencies,
:specs,
:platforms,
@@ -97,6 +98,7 @@ module Bundler
def initialize(lockfile, strict: false)
@platforms = []
@sources = []
@metadata_source = Source::Metadata.new
@dependencies = {}
@parse_method = nil
@specs = {}
@@ -252,7 +254,12 @@ module Bundler
version = Gem::Version.new(version)
platform = platform ? Gem::Platform.new(platform) : Gem::Platform::RUBY
full_name = Gem::NameTuple.new(name, version, platform).full_name
return unless spec = @specs[full_name]
spec = @specs[full_name]
if name == "bundler"
spec ||= LazySpecification.new(name, version, platform, @metadata_source)
end
return unless spec
if checksums
checksums.split(",") do |lock_checksum|
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-ADD" "1" "March 2026" ""
.TH "BUNDLE\-ADD" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-BINSTUBS" "1" "March 2026" ""
.TH "BUNDLE\-BINSTUBS" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-binstubs\fR \- Install the binstubs of the listed gems
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-CACHE" "1" "March 2026" ""
.TH "BUNDLE\-CACHE" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-CHECK" "1" "March 2026" ""
.TH "BUNDLE\-CHECK" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-CLEAN" "1" "March 2026" ""
.TH "BUNDLE\-CLEAN" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory
.SH "SYNOPSIS"
+2 -2
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-CONFIG" "1" "March 2026" ""
.TH "BUNDLE\-CONFIG" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-config\fR \- Set bundler configuration options
.SH "SYNOPSIS"
@@ -172,7 +172,7 @@ Whether Bundler will install gems into the default system path (\fBGem\.dir\fR)\
\fBplugins\fR (\fBBUNDLE_PLUGINS\fR)
Enable Bundler's experimental plugin system\.
.TP
\fBprefer_patch\fR (BUNDLE_PREFER_PATCH)
\fBprefer_patch\fR (\fBBUNDLE_PREFER_PATCH\fR)
Prefer updating only to next patch version during updates\. Makes \fBbundle update\fR calls equivalent to \fBbundler update \-\-patch\fR\.
.TP
\fBredirect\fR (\fBBUNDLE_REDIRECT\fR)
+1 -1
View File
@@ -223,7 +223,7 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
Whether Bundler will install gems into the default system path (`Gem.dir`).
* `plugins` (`BUNDLE_PLUGINS`):
Enable Bundler's experimental plugin system.
* `prefer_patch` (BUNDLE_PREFER_PATCH):
* `prefer_patch` (`BUNDLE_PREFER_PATCH`):
Prefer updating only to next patch version during updates. Makes `bundle update` calls equivalent to `bundler update --patch`.
* `redirect` (`BUNDLE_REDIRECT`):
The number of redirects allowed for network requests. Defaults to `5`.
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-CONSOLE" "1" "March 2026" ""
.TH "BUNDLE\-CONSOLE" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-console\fR \- Open an IRB session with the bundle pre\-loaded
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-DOCTOR" "1" "March 2026" ""
.TH "BUNDLE\-DOCTOR" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-doctor\fR \- Checks the bundle for common problems
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-ENV" "1" "March 2026" ""
.TH "BUNDLE\-ENV" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-env\fR \- Print information about the environment Bundler is running under
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-EXEC" "1" "March 2026" ""
.TH "BUNDLE\-EXEC" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-exec\fR \- Execute a command in the context of the bundle
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-FUND" "1" "March 2026" ""
.TH "BUNDLE\-FUND" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-fund\fR \- Lists information about gems seeking funding assistance
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-GEM" "1" "March 2026" ""
.TH "BUNDLE\-GEM" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-HELP" "1" "March 2026" ""
.TH "BUNDLE\-HELP" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-help\fR \- Displays detailed help for each subcommand
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-INFO" "1" "March 2026" ""
.TH "BUNDLE\-INFO" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-info\fR \- Show information for the given gem in your bundle
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-INIT" "1" "March 2026" ""
.TH "BUNDLE\-INIT" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-init\fR \- Generates a Gemfile into the current working directory
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-INSTALL" "1" "March 2026" ""
.TH "BUNDLE\-INSTALL" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-install\fR \- Install the dependencies specified in your Gemfile
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-ISSUE" "1" "March 2026" ""
.TH "BUNDLE\-ISSUE" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-issue\fR \- Get help reporting Bundler issues
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-LICENSES" "1" "March 2026" ""
.TH "BUNDLE\-LICENSES" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-licenses\fR \- Print the license of all gems in the bundle
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-LIST" "1" "March 2026" ""
.TH "BUNDLE\-LIST" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-list\fR \- List all the gems in the bundle
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-LOCK" "1" "March 2026" ""
.TH "BUNDLE\-LOCK" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-lock\fR \- Creates / Updates a lockfile without installing
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-OPEN" "1" "March 2026" ""
.TH "BUNDLE\-OPEN" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-open\fR \- Opens the source directory for a gem in your bundle
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-OUTDATED" "1" "March 2026" ""
.TH "BUNDLE\-OUTDATED" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-outdated\fR \- List installed gems with newer versions available
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-PLATFORM" "1" "March 2026" ""
.TH "BUNDLE\-PLATFORM" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-platform\fR \- Displays platform compatibility information
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-PLUGIN" "1" "March 2026" ""
.TH "BUNDLE\-PLUGIN" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-plugin\fR \- Manage Bundler plugins
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-PRISTINE" "1" "March 2026" ""
.TH "BUNDLE\-PRISTINE" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-pristine\fR \- Restores installed gems to their pristine condition
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-REMOVE" "1" "March 2026" ""
.TH "BUNDLE\-REMOVE" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-remove\fR \- Removes gems from the Gemfile
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-SHOW" "1" "March 2026" ""
.TH "BUNDLE\-SHOW" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-UPDATE" "1" "March 2026" ""
.TH "BUNDLE\-UPDATE" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-update\fR \- Update your gems to the latest available versions
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE\-VERSION" "1" "March 2026" ""
.TH "BUNDLE\-VERSION" "1" "April 2026" ""
.SH "NAME"
\fBbundle\-version\fR \- Prints Bundler version information
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "BUNDLE" "1" "March 2026" ""
.TH "BUNDLE" "1" "April 2026" ""
.SH "NAME"
\fBbundle\fR \- Ruby Dependency Management
.SH "SYNOPSIS"
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
.TH "GEMFILE" "5" "March 2026" ""
.TH "GEMFILE" "5" "April 2026" ""
.SH "NAME"
\fBGemfile\fR \- A format for describing gem dependencies for Ruby programs
.SH "SYNOPSIS"
+4
View File
@@ -58,6 +58,10 @@ module Bundler
def version_message(spec)
"#{spec.name} #{spec.version}"
end
def checksum_store
@checksum_store ||= Checksum::Store.new
end
end
end
end
+1 -1
View File
@@ -508,7 +508,7 @@ module Bundler
# We are using a mutex to reaed and write from/to the hash.
# The reason this double synchronization was added is for performance
# and lock the mutex for the shortest possible amount of time. Otherwise,
# and to lock the mutex for the shortest possible amount of time. Otherwise,
# all threads are fighting over this mutex and when it gets acquired it gets locked
# until a threads finishes downloading a gem, leaving the other threads waiting
# doing nothing.
@@ -22,6 +22,12 @@ Gem::Specification.new do |spec|
spec.metadata["changelog_uri"] = "<%= config[:changelog_uri] %>"
<%- end -%>
# Uncomment the line below to require MFA for gem pushes.
# This helps protect your gem from supply chain attacks by ensuring
# no one can publish a new version without multi-factor authentication.
# See: https://guides.rubygems.org/mfa-requirement-opt-in/
# spec.metadata["rubygems_mfa_required"] = "true"
# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
gemspec = File.basename(__FILE__)
@@ -48,5 +54,5 @@ Gem::Specification.new do |spec|
<%- end -%>
# For more information and examples about making a new gem, check out our
# guide at: https://bundler.io/guides/creating_gem.html
# guide at: https://guides.rubygems.org/make-your-own-gem/
end
+1 -1
View File
@@ -1,7 +1,7 @@
# frozen_string_literal: false
module Bundler
VERSION = "4.0.10".freeze
VERSION = "4.0.11".freeze
def self.bundler_major_version
@bundler_major_version ||= gem_version.segments.first
+1 -1
View File
@@ -9,7 +9,7 @@
require "rbconfig"
module Gem
VERSION = "4.0.10"
VERSION = "4.0.11"
end
require_relative "rubygems/defaults"
@@ -42,7 +42,7 @@ class Gem::Commands::SpecificationCommand < Gem::Command
def arguments # :nodoc:
<<-ARGS
GEMFILE name of gem to show the gemspec for
GEM_OR_FILE gem name or a .gem file to show the gemspec for
FIELD name of gemspec field to show
ARGS
end
@@ -68,7 +68,7 @@ Specific fields in the specification can be extracted in YAML format:
end
def usage # :nodoc:
"#{program_name} [GEMFILE] [FIELD]"
"#{program_name} [GEM_OR_FILE] [FIELD]"
end
def execute
@@ -77,7 +77,7 @@ Specific fields in the specification can be extracted in YAML format:
unless gem
raise Gem::CommandLineError,
"Please specify a gem name or file on the command line"
"Please specify a gem name or a .gem file on the command line"
end
case v = options[:version]
@@ -3,18 +3,17 @@
require "bundler/installer/parallel_installer"
RSpec.describe Bundler::ParallelInstaller::SpecInstallation do
let!(:dep) do
a_spec = Object.new
def a_spec.name
"I like tests"
end
def a_spec.full_name
"I really like tests"
end
a_spec
def build_spec(name, extensions: [])
spec = Object.new
spec.define_singleton_method(:name) { name }
spec.define_singleton_method(:full_name) { "#{name}-1.0" }
spec.define_singleton_method(:extensions) { extensions }
spec.define_singleton_method(:dependencies) { [] }
spec
end
let!(:dep) { build_spec("I like tests") }
describe "#ready_to_enqueue?" do
context "when in enqueued state" do
it "is falsey" do
@@ -39,29 +38,51 @@ RSpec.describe Bundler::ParallelInstaller::SpecInstallation do
end
describe "#dependencies_installed?" do
context "when all dependencies are installed" do
it "returns true" do
dependencies = []
dependencies << instance_double("SpecInstallation", spec: "alpha", name: "alpha", installed?: true, all_dependencies: [], type: :production)
dependencies << instance_double("SpecInstallation", spec: "beta", name: "beta", installed?: true, all_dependencies: [], type: :production)
all_specs = dependencies + [instance_double("SpecInstallation", spec: "gamma", name: "gamma", installed?: false, all_dependencies: [], type: :production)]
it "returns true when all dependencies are installed" do
alpha = described_class.new(build_spec("alpha"))
alpha.dependencies = []
beta = described_class.new(build_spec("beta"))
beta.dependencies = [alpha]
gamma = described_class.new(build_spec("gamma"))
gamma.dependencies = [beta]
expect(gamma.dependencies_installed?({})).to be_falsey
expect(gamma.dependencies_installed?({ "beta" => true })).to be_falsey
expect(gamma.dependencies_installed?({ "alpha" => true, "beta" => true })).to be_truthy
end
end
describe "#ready_to_install?" do
context "when spec has no extensions" do
it "returns true regardless of dependencies" do
beta = described_class.new(build_spec("beta"))
beta.dependencies = []
spec = described_class.new(dep)
allow(spec).to receive(:all_dependencies).and_return(dependencies)
installed_specs = all_specs.select(&:installed?).map {|s| [s.name, true] }.to_h
expect(spec.dependencies_installed?(installed_specs)).to be_truthy
spec.state = :downloaded
spec.dependencies = [beta]
expect(spec.ready_to_install?({})).to be_truthy
end
end
context "when all dependencies are not installed" do
it "returns false" do
dependencies = []
dependencies << instance_double("SpecInstallation", spec: "alpha", name: "alpha", installed?: false, all_dependencies: [], type: :production)
dependencies << instance_double("SpecInstallation", spec: "beta", name: "beta", installed?: true, all_dependencies: [], type: :production)
all_specs = dependencies + [instance_double("SpecInstallation", spec: "gamma", name: "gamma", installed?: false, all_dependencies: [], type: :production)]
spec = described_class.new(dep)
allow(spec).to receive(:all_dependencies).and_return(dependencies)
installed_specs = all_specs.select(&:installed?).map {|s| [s.name, true] }.to_h
expect(spec.dependencies_installed?(installed_specs)).to be_falsey
context "when spec has extensions" do
it "returns true when all dependencies are installed" do
alpha = described_class.new(build_spec("alpha"))
alpha.dependencies = []
beta = described_class.new(build_spec("beta"))
beta.dependencies = [alpha]
gamma = described_class.new(build_spec("gamma", extensions: ["ext/Rakefile"]))
gamma.state = :downloaded
gamma.dependencies = [beta]
expect(gamma.ready_to_install?({})).to be_falsey
expect(gamma.ready_to_install?({ "beta" => true })).to be_falsey
expect(gamma.ready_to_install?({ "alpha" => true, "beta" => true })).to be_truthy
end
end
end
+42
View File
@@ -1379,6 +1379,48 @@ RSpec.describe "bundle install with gem sources" do
end
end
describe "when a native extension requires a transitive dependency at build time" do
before do
build_repo4 do
build_gem "alpha", "1.0.0" do |s|
extension = "ext/alpha/extconf.rb"
s.extensions = extension
s.write(extension, <<~CODE)
require "mkmf"
sleep 1
create_makefile("alpha")
CODE
s.write "lib/alpha.rb", "ALPHA = '1.0.0'"
end
build_gem "beta", "1.0.0" do |s|
s.add_dependency "alpha"
s.write "lib/beta.rb", "require 'alpha'\nBETA = '1.0.0'"
end
build_gem "gamma", "1.0.0" do |s|
s.add_dependency "beta"
extension = "ext/gamma/extconf.rb"
s.extensions = extension
s.write(extension, <<~EXTCONF)
require "beta"
require "mkmf"
create_makefile("gamma")
EXTCONF
end
end
end
it "installs successfully" do
install_gemfile <<~G
source "https://gem.repo4"
gem "gamma"
G
expect(the_bundle).to include_gems "alpha 1.0.0", "beta 1.0.0", "gamma 1.0.0"
end
end
describe "when configured path is UTF-8 and a file inside a gem package too" do
let(:app_path) do
path = tmp("♥")
+5 -4
View File
@@ -2295,6 +2295,10 @@ RSpec.describe "bundle lock" do
bundle("lock --add-checksums", artifice: "endpoint")
checksums = checksums_section_when_enabled do |c|
c.no_checksum "warning", "18.0.0"
end
expect(lockfile).to eq <<~L
GEM
remote: https://gem.repo4/
@@ -2306,10 +2310,7 @@ RSpec.describe "bundle lock" do
DEPENDENCIES
warning
CHECKSUMS
warning (18.0.0)
#{checksums}
BUNDLED WITH
#{Bundler::VERSION}
L
+9
View File
@@ -645,6 +645,15 @@ RSpec.describe "bundle gem" do
to match(/example\.com/)
end
it "includes a commented-out rubygems_mfa_required metadata hint" do
bundle "gem #{gem_name}"
gemspec_contents = bundled_app("#{gem_name}/#{gem_name}.gemspec").read
expect(gemspec_contents).to include('# spec.metadata["rubygems_mfa_required"] = "true"')
expect(gemspec_contents).to include("https://guides.rubygems.org/mfa-requirement-opt-in/")
end
it "sets a minimum ruby version" do
bundle "gem #{gem_name}"
+5 -3
View File
@@ -1419,9 +1419,7 @@ RSpec.describe "bundle update --ruby" do
#{lockfile_platforms}
DEPENDENCIES
CHECKSUMS
#{checksums_section_when_enabled}
RUBY VERSION
#{Bundler::RubyVersion.system}
@@ -1537,6 +1535,7 @@ RSpec.describe "bundle update --bundler" do
checksums = checksums_section do |c|
c.checksum(gem_repo4, "myrack", "1.0")
c.checksum(gem_repo4, "bundler", "999.0.0")
end
install_gemfile <<-G
@@ -1621,6 +1620,7 @@ RSpec.describe "bundle update --bundler" do
checksums = checksums_section do |c|
c.checksum(gem_repo4, "myrack", "1.0")
c.checksum(gem_repo4, "bundler", "9.9.9")
end
install_gemfile <<-G
@@ -1706,6 +1706,7 @@ RSpec.describe "bundle update --bundler" do
checksums = checksums_section_when_enabled do |c|
c.checksum(gem_repo4, "myrack", "1.0")
end
checksums.delete("bundler")
expect(lockfile).to eq <<~L
GEM
@@ -1745,6 +1746,7 @@ RSpec.describe "bundle update --bundler" do
# Only updates properly on modern RubyGems.
checksums = checksums_section_when_enabled do |c|
c.checksum(gem_repo4, "myrack", "1.0")
c.checksum(local_gem_path, "bundler", "9.0.0", Gem::Platform::RUBY, "cache")
end
expect(lockfile).to eq <<~L
+2 -2
View File
@@ -478,7 +478,7 @@ RSpec.describe "bundle install with git sources" do
update_git("foo", path: repo, tag: tag)
install_gemfile <<-G
source "https://gem.repo1"
source "https://gem.repo1"
git "#{repo}", :tag => #{tag.dump} do
gem "foo"
end
@@ -1078,7 +1078,7 @@ RSpec.describe "bundle install with git sources" do
expect(out).to eq("WIN")
end
it "does not to a remote fetch if the revision is cached locally" do
it "does not do a remote fetch if the revision is cached locally" do
build_git "foo"
install_gemfile <<-G
+1 -1
View File
@@ -358,7 +358,7 @@ RSpec.describe "bundle install with install-time dependencies" do
#{lockfile_platforms}
DEPENDENCIES
parallel_tests
rubocop
#{checksums}
BUNDLED WITH
#{Bundler::VERSION}
@@ -46,4 +46,4 @@ DEPENDENCIES
tapioca
BUNDLED WITH
4.0.10
4.0.11
@@ -36,4 +36,4 @@ DEPENDENCIES
warbler!
BUNDLED WITH
4.0.10
4.0.11
+7 -2
View File
@@ -1283,7 +1283,12 @@ end
end
context "is not present" do
it "does not change the lock" do
# Skipped on ruby-core because `ruby "require 'bundler/setup'"` does not
# activate bundler as a gem there, so Source::Metadata falls back to a
# synthetic spec whose cache_file does not exist on disk and
# LockfileGenerator#bundler_checksum drops the bundler checksum, while
# the on-disk lockfile still has it.
it "does not change the lock", :ruby_repo do
expect { ruby "require 'bundler/setup'" }.not_to change { lockfile }
end
end
@@ -1329,7 +1334,7 @@ end
gem "bar", :git => "#{lib_path("bar-1.0")}"
G
bundle :install
bundle :install, env: { "BUNDLE_LOCKFILE_CHECKSUMS" => "false" }
ruby <<-RUBY, artifice: nil
require 'bundler/setup'
+14 -5
View File
@@ -3,6 +3,8 @@
module Spec
module Checksums
class ChecksumsBuilder
attr_reader :bundler_registered
def initialize(enabled = true, &block)
@enabled = enabled
@checksums = {}
@@ -14,9 +16,11 @@ module Spec
@checksums = @checksums.dup
end
def checksum(repo, name, version, platform = Gem::Platform::RUBY)
def checksum(repo, name, version, platform = Gem::Platform::RUBY, folder = "gems")
@bundler_registered = true if name == "bundler"
name_tuple = Gem::NameTuple.new(name, version, platform)
gem_file = File.join(repo, "gems", "#{name_tuple.full_name}.gem")
gem_file = File.join(repo, folder, "#{name_tuple.full_name}.gem")
File.open(gem_file, "rb") do |f|
register(name_tuple, Bundler::Checksum.from_gem(f, "#{gem_file} (via ChecksumsBuilder#checksum)"))
end
@@ -50,8 +54,13 @@ module Spec
end
end
def checksums_section(enabled = true, &block)
ChecksumsBuilder.new(enabled, &block)
def checksums_section(enabled = true, bundler_checksum: true, &block)
ChecksumsBuilder.new(enabled, &block).tap do |builder|
next if builder.bundler_registered || !bundler_checksum
next if Bundler::VERSION.to_s.end_with?(".dev")
builder.checksum(system_gem_path, "bundler", Bundler::VERSION, Gem::Platform::RUBY, "cache")
end
end
def checksums_section_when_enabled(target_lockfile = nil, &block)
@@ -64,7 +73,7 @@ module Spec
end
def checksum_to_lock(*args)
checksums_section do |c|
checksums_section(true, bundler_checksum: false) do |c|
c.checksum(*args)
end.to_s.sub(/^CHECKSUMS\n/, "").strip
end
@@ -148,7 +148,7 @@ class TestGemCommandsPushCommand < Gem::TestCase
spec.metadata["allowed_push_host"] = "https://privategemserver.example"
end
@response = "Successfully registered gem: freewill (1.0.0)"
@response = "Successfully registered gem: freebird (1.0.1)"
@fetcher.data["#{@spec.metadata["allowed_push_host"]}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK")
@fetcher.data["#{Gem.host}/api/v1/gems"] =
["fail", 500, "Internal Server Error"]
+2 -2
View File
@@ -221,7 +221,7 @@ class TestStubSpecification < Gem::TestCase
end
def stub_with_version
spec = File.join @gemhome, "specifications", "stub_e-2.gemspec"
spec = File.join @gemhome, "specifications", "stub_v-with-version.gemspec"
File.open spec, "w" do |io|
io.write <<~STUB
# -*- encoding: utf-8 -*-
@@ -244,7 +244,7 @@ class TestStubSpecification < Gem::TestCase
end
def stub_without_version
spec = File.join @gemhome, "specifications", "stub-2.gemspec"
spec = File.join @gemhome, "specifications", "stub_v-without-version.gemspec"
File.open spec, "w" do |io|
io.write <<~STUB
# -*- encoding: utf-8 -*-
+1 -1
View File
@@ -129,4 +129,4 @@ CHECKSUMS
turbo_tests (2.2.5) sha256=3fa31497d12976d11ccc298add29107b92bda94a90d8a0a5783f06f05102509f
BUNDLED WITH
4.0.10
4.0.11
+1 -1
View File
@@ -156,4 +156,4 @@ CHECKSUMS
unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
BUNDLED WITH
4.0.10
4.0.11
+1 -1
View File
@@ -176,4 +176,4 @@ CHECKSUMS
unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
BUNDLED WITH
4.0.10
4.0.11
+1 -1
View File
@@ -103,4 +103,4 @@ CHECKSUMS
tilt (2.6.1) sha256=35a99bba2adf7c1e362f5b48f9b581cce4edfba98117e34696dde6d308d84770
BUNDLED WITH
4.0.10
4.0.11