Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Manifest.txt
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ bundler/lib/bundler/match_platform.rb
bundler/lib/bundler/match_remote_metadata.rb
bundler/lib/bundler/materialization.rb
bundler/lib/bundler/mirror.rb
bundler/lib/bundler/override.rb
bundler/lib/bundler/plugin.rb
bundler/lib/bundler/plugin/api.rb
bundler/lib/bundler/plugin/api/source.rb
Expand Down
1 change: 1 addition & 0 deletions bundler/lib/bundler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ module Bundler
autoload :MatchRemoteMetadata, File.expand_path("bundler/match_remote_metadata", __dir__)
autoload :Materialization, File.expand_path("bundler/materialization", __dir__)
autoload :NULL, File.expand_path("bundler/constants", __dir__)
autoload :Override, File.expand_path("bundler/override", __dir__)
autoload :ProcessLock, File.expand_path("bundler/process_lock", __dir__)
autoload :RemoteSpecification, File.expand_path("bundler/remote_specification", __dir__)
autoload :Resolver, File.expand_path("bundler/resolver", __dir__)
Expand Down
41 changes: 36 additions & 5 deletions bundler/lib/bundler/definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ class << self
attr_accessor :no_lock
end

attr_writer :lockfile
attr_writer :lockfile, :overrides

attr_reader(
:dependencies,
:locked_checksums,
:locked_deps,
:locked_gems,
:overrides,
:platforms,
:ruby_version,
:lockfile,
Expand Down Expand Up @@ -58,7 +59,7 @@ def self.build(gemfile, lockfile, unlock)
# to be updated or true if all gems should be updated
# @param ruby_version [Bundler::RubyVersion, nil] Requested Ruby Version
# @param optional_groups [Array(String)] A list of optional groups
def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, optional_groups = [], gemfiles = [])
def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, optional_groups = [], gemfiles = [], overrides = [])
unlock ||= {}

if unlock == true
Expand Down Expand Up @@ -88,6 +89,7 @@ def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, opti
@specs = nil
@ruby_version = ruby_version
@gemfiles = gemfiles
@overrides = overrides

@lockfile = lockfile
@lockfile_contents = String.new
Expand Down Expand Up @@ -633,7 +635,20 @@ def resolver
end

def expanded_dependencies
dependencies_with_bundler + metadata_dependencies
apply_overrides_to(dependencies_with_bundler) + metadata_dependencies
end

def apply_overrides_to(deps)
return deps if @overrides.empty?
deps.map {|dep| apply_override_to(dep) }
end

def apply_override_to(dep)
override = @overrides.find {|o| o.target == dep.name && o.field == :version }
return dep unless override
new_dep = dep.dup
new_dep.instance_variable_set(:@requirement, override.apply_to(dep.requirement))
new_dep
end

def dependencies_with_bundler
Expand Down Expand Up @@ -1029,7 +1044,7 @@ def converge_dependencies
@locked_specs.delete(locked_specs.select {|s| s.source != dep.source })
end

unless dep.matches_spec?(locked_specs.first)
unless apply_override_to(dep).matches_spec?(locked_specs.first)
@gems_to_unlock << name
dep_changed = true
end
Expand All @@ -1039,9 +1054,25 @@ def converge_dependencies
@changed_dependencies << name if dep_changed
end

converge_overrides_outside_dependencies

@changed_dependencies.any?
end

def converge_overrides_outside_dependencies
@overrides.each do |override|
next unless override.target.is_a?(String)

name = override.target
next if @changed_dependencies.include?(name)
next if @dependencies.any? {|d| d.name == name }
next if @originally_locked_specs[name].empty?

@gems_to_unlock << name
@changed_dependencies << name
end
end

# Remove elements from the locked specs that are expired. This will most
# commonly happen if the Gemfile has changed since the lockfile was last
# generated
Expand Down Expand Up @@ -1273,7 +1304,7 @@ def unlocked_resolution_base

def new_resolution_base(last_resolve:, unlock:)
new_resolution_platforms = @current_platform_missing ? @new_platforms + [Bundler.local_platform] : @new_platforms
Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms)
Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms, overrides: @overrides)
end

def new_resolver(base)
Expand Down
54 changes: 52 additions & 2 deletions bundler/lib/bundler/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def self.evaluate(gemfile, lockfile, unlock)
GITHUB_PULL_REQUEST_URL = %r{\Ahttps://github\.com/([A-Za-z0-9_\-\.]+/[A-Za-z0-9_\-\.]+)/pull/(\d+)\z}
GITLAB_MERGE_REQUEST_URL = %r{\Ahttps://gitlab\.com/([A-Za-z0-9_\-\./]+)/-/merge_requests/(\d+)\z}

attr_reader :gemspecs, :gemfile
attr_reader :gemspecs, :gemfile, :overrides
attr_accessor :dependencies

def initialize
Expand All @@ -40,6 +40,7 @@ def initialize
@gemfile = nil
@gemfiles = []
@lockfile = nil
@overrides = []
add_git_sources
end

Expand Down Expand Up @@ -184,10 +185,31 @@ def github(repo, options = {})
with_source(git_source) { yield }
end

SUPPORTED_OVERRIDE_FIELDS = [:version].freeze
SUPPORTED_OVERRIDE_SYMBOL_OPERATIONS = [:ignore_upper].freeze

def override(target, **operations)
validate_override_target!(target)

if target == :all && operations.key?(:version)
raise ArgumentError, "`override :all, version:` is not allowed; version requirements are per-gem"
end

operations.each do |field, operation|
validate_override_field!(field)
validate_override_operation!(operation)
validate_override_uniqueness!(target, field)
end

operations.each do |field, operation|
@overrides << Override.new(target, field, operation)
end
end

def to_definition(lockfile, unlock)
check_primary_source_safety
lockfile = @lockfile unless @lockfile.nil?
Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version, @optional_groups, @gemfiles)
Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version, @optional_groups, @gemfiles, @overrides)
end

def group(*args, &blk)
Expand Down Expand Up @@ -244,6 +266,34 @@ def check_primary_source_safety

private

def validate_override_target!(target)
return if target == :all
return if target.is_a?(String)
raise ArgumentError, "override target must be :all or a gem name string, got #{target.inspect}"
end

def validate_override_field!(field)
return if SUPPORTED_OVERRIDE_FIELDS.include?(field)
raise ArgumentError, "unsupported override field `#{field}:`; only `version:` is currently supported"
end

def validate_override_operation!(operation)
case operation
when String, nil
# ok
when Symbol
return if SUPPORTED_OVERRIDE_SYMBOL_OPERATIONS.include?(operation)
raise ArgumentError, "unsupported override operation: #{operation.inspect}"
else
raise ArgumentError, "override operation must be a String, Symbol, or nil, got #{operation.inspect}"
end
end

def validate_override_uniqueness!(target, field)
return unless @overrides.any? {|o| o.target == target && o.field == field }
raise ArgumentError, "duplicate override for #{target.inspect} `#{field}:`"
end

def add_dependency(name, version = nil, options = {})
options["gemfile"] = @gemfile
options["source"] ||= @source
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-add.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-ADD" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-binstubs.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-BINSTUBS" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-binstubs\fR \- Install the binstubs of the listed gems
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-cache.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-CACHE" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-check.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-CHECK" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-clean.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-CLEAN" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-config.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-CONFIG" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-config\fR \- Set bundler configuration options
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-console.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-CONSOLE" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-console\fR \- Open an IRB session with the bundle pre\-loaded
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-doctor.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-DOCTOR" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-doctor\fR \- Checks the bundle for common problems
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-env.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-ENV" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-env\fR \- Print information about the environment Bundler is running under
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-exec.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-EXEC" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-exec\fR \- Execute a command in the context of the bundle
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-fund.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-FUND" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-fund\fR \- Lists information about gems seeking funding assistance
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-gem.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-GEM" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-help.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-HELP" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-help\fR \- Displays detailed help for each subcommand
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-info.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-INFO" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-info\fR \- Show information for the given gem in your bundle
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-init.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-INIT" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-init\fR \- Generates a Gemfile into the current working directory
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-install.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-INSTALL" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-install\fR \- Install the dependencies specified in your Gemfile
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-issue.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-ISSUE" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-issue\fR \- Get help reporting Bundler issues
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-licenses.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-LICENSES" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-licenses\fR \- Print the license of all gems in the bundle
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-list.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-LIST" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-list\fR \- List all the gems in the bundle
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-lock.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-LOCK" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-lock\fR \- Creates / Updates a lockfile without installing
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-open.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-OPEN" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-open\fR \- Opens the source directory for a gem in your bundle
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-outdated.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-OUTDATED" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-outdated\fR \- List installed gems with newer versions available
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-platform.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-PLATFORM" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-platform\fR \- Displays platform compatibility information
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-plugin.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-PLUGIN" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-plugin\fR \- Manage Bundler plugins
.SH "SYNOPSIS"
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/man/bundle-pristine.1
Original file line number Diff line number Diff line change
@@ -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" "April 2026" ""
.TH "BUNDLE\-PRISTINE" "1" "May 2026" ""
.SH "NAME"
\fBbundle\-pristine\fR \- Restores installed gems to their pristine condition
.SH "SYNOPSIS"
Expand Down
Loading
Loading