bundler 4.1.0.beta1 → 4.1.0.beta2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/bundler/build_metadata.rb +2 -2
- data/lib/bundler/cli/common.rb +4 -0
- data/lib/bundler/cli/doctor/ssl.rb +4 -8
- data/lib/bundler/cli/info.rb +1 -1
- data/lib/bundler/cli/lock.rb +14 -3
- data/lib/bundler/cli/open.rb +7 -1
- data/lib/bundler/cli/outdated.rb +8 -10
- data/lib/bundler/cli/platform.rb +15 -1
- data/lib/bundler/cli/show.rb +5 -1
- data/lib/bundler/cli/update.rb +1 -1
- data/lib/bundler/cli.rb +22 -7
- data/lib/bundler/constants.rb +1 -1
- data/lib/bundler/definition.rb +64 -14
- data/lib/bundler/dsl.rb +61 -3
- data/lib/bundler/fetcher/downloader.rb +5 -1
- data/lib/bundler/gem_helper.rb +1 -1
- data/lib/bundler/installer/parallel_installer.rb +2 -1
- data/lib/bundler/installer.rb +5 -1
- data/lib/bundler/lazy_specification.rb +1 -1
- data/lib/bundler/lockfile_parser.rb +1 -1
- data/lib/bundler/man/bundle-info.1 +4 -1
- data/lib/bundler/man/bundle-info.1.ronn +4 -0
- data/lib/bundler/man/bundle-lock.1 +2 -2
- data/lib/bundler/man/bundle-lock.1.ronn +4 -3
- data/lib/bundler/man/bundle-open.1 +4 -1
- data/lib/bundler/man/bundle-open.1.ronn +4 -1
- data/lib/bundler/man/bundle-outdated.1 +1 -1
- data/lib/bundler/man/bundle-outdated.1.ronn +1 -1
- data/lib/bundler/man/bundle-show.1 +4 -1
- data/lib/bundler/man/bundle-show.1.ronn +4 -0
- data/lib/bundler/man/bundle-update.1 +3 -3
- data/lib/bundler/man/bundle-update.1.ronn +5 -3
- data/lib/bundler/man/gemfile.5 +33 -1
- data/lib/bundler/man/gemfile.5.ronn +53 -2
- data/lib/bundler/materialization.rb +3 -1
- data/lib/bundler/override.rb +30 -2
- data/lib/bundler/resolver.rb +28 -4
- data/lib/bundler/self_manager.rb +15 -9
- data/lib/bundler/settings.rb +10 -26
- data/lib/bundler/source/git/git_proxy.rb +39 -2
- data/lib/bundler/source/git.rb +34 -7
- data/lib/bundler/source/rubygems_aggregate.rb +1 -1
- data/lib/bundler/source_map.rb +7 -3
- data/lib/bundler/spec_set.rb +8 -4
- data/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt +1 -1
- data/lib/bundler/version.rb +1 -1
- data/lib/bundler.rb +1 -3
- data/lib/rubygems/compact_index_client/http_fetcher.rb +5 -3
- metadata +391 -390
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3c0da83afaf51ba4984bf6afadad1dc16ba90dd523a7a70ed5ca4e353fb5a3ef
|
|
4
|
+
data.tar.gz: 252ab201fa16d64d654b43f3f642d622dbaa94c653b90bddea01af7f8dfdf6a7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d3d0486d8ace2df28048406ccba0335f679c5d7bef8e3ab20c8c72628fb1500ddc3d80ac8ae897b63ecb268a33a7fcb9a826b5833414ee7e63fb46c37e674528
|
|
7
|
+
data.tar.gz: e9e6a99a38ff138d0fb3bc992843384bf06f732513c65e015c7758fa72dd210c5d369aced9826813799ca189b073270499a109cc4b5290183e67db5010430d3c
|
|
@@ -4,8 +4,8 @@ module Bundler
|
|
|
4
4
|
# Represents metadata from when the Bundler gem was built.
|
|
5
5
|
module BuildMetadata
|
|
6
6
|
# begin ivars
|
|
7
|
-
@built_at = "2026-
|
|
8
|
-
@git_commit_sha = "
|
|
7
|
+
@built_at = "2026-10-08".freeze
|
|
8
|
+
@git_commit_sha = "f8b8b02".freeze
|
|
9
9
|
# end ivars
|
|
10
10
|
|
|
11
11
|
# A hash representation of the build metadata.
|
data/lib/bundler/cli/common.rb
CHANGED
|
@@ -122,6 +122,10 @@ module Bundler
|
|
|
122
122
|
raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies)
|
|
123
123
|
end
|
|
124
124
|
|
|
125
|
+
def self.select_spec_with_match_type(name, options)
|
|
126
|
+
select_spec(name, options["exact-match"] ? nil : :regex_match)
|
|
127
|
+
end
|
|
128
|
+
|
|
125
129
|
def self.default_gem_spec(name)
|
|
126
130
|
gem_spec = Gem::Specification.find_all_by_name(name).last
|
|
127
131
|
gem_spec if gem_spec&.default_gem?
|
|
@@ -124,14 +124,10 @@ module Bundler
|
|
|
124
124
|
ctx = OpenSSL::SSL::SSLContext.new
|
|
125
125
|
supported = true
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
supported = false
|
|
132
|
-
end
|
|
133
|
-
else
|
|
134
|
-
supported = OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_2) # rubocop:disable Naming/VariableNumber
|
|
127
|
+
begin
|
|
128
|
+
ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
|
|
129
|
+
rescue OpenSSL::SSL::SSLError, NameError
|
|
130
|
+
supported = false
|
|
135
131
|
end
|
|
136
132
|
|
|
137
133
|
Bundler.ui.warn(<<~EOM) unless supported
|
data/lib/bundler/cli/info.rb
CHANGED
data/lib/bundler/cli/lock.rb
CHANGED
|
@@ -74,10 +74,21 @@ module Bundler
|
|
|
74
74
|
puts definition.to_lock
|
|
75
75
|
else
|
|
76
76
|
file = options[:lockfile]
|
|
77
|
-
file =
|
|
77
|
+
file = if file
|
|
78
|
+
Pathname.new(file).expand_path
|
|
79
|
+
elsif ENV["BUNDLE_LOCKFILE"].to_s.empty?
|
|
80
|
+
definition.lockfile
|
|
81
|
+
else
|
|
82
|
+
# BUNDLE_LOCKFILE outranks the lockfile method in the Gemfile, see gemfile(5)
|
|
83
|
+
Bundler.default_lockfile
|
|
84
|
+
end
|
|
78
85
|
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
if file
|
|
87
|
+
puts "Writing lockfile to #{file}"
|
|
88
|
+
definition.write_lock(file, false)
|
|
89
|
+
else
|
|
90
|
+
Bundler.ui.warn "Not writing a lockfile because the Gemfile sets `lockfile false`"
|
|
91
|
+
end
|
|
81
92
|
end
|
|
82
93
|
|
|
83
94
|
Bundler::CLI::Common.output_cooldown_skipped_summary(definition)
|
data/lib/bundler/cli/open.rb
CHANGED
|
@@ -13,7 +13,7 @@ module Bundler
|
|
|
13
13
|
raise InvalidOption, "Cannot specify `--path` option without a value" if !@path.nil? && @path.empty?
|
|
14
14
|
editor = [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? }
|
|
15
15
|
return Bundler.ui.info("To open a bundled gem, set $EDITOR or $BUNDLER_EDITOR") unless editor
|
|
16
|
-
return unless spec =
|
|
16
|
+
return unless spec = spec_for_gem(name)
|
|
17
17
|
if spec.default_gem?
|
|
18
18
|
Bundler.ui.info "Unable to open #{name} because it's a default gem, so the directory it would normally be installed to does not exist."
|
|
19
19
|
else
|
|
@@ -35,5 +35,11 @@ module Bundler
|
|
|
35
35
|
require "shellwords"
|
|
36
36
|
Shellwords.split(editor)
|
|
37
37
|
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def spec_for_gem(name)
|
|
42
|
+
Bundler::CLI::Common.select_spec_with_match_type(name, options)
|
|
43
|
+
end
|
|
38
44
|
end
|
|
39
45
|
end
|
data/lib/bundler/cli/outdated.rb
CHANGED
|
@@ -90,7 +90,9 @@ module Bundler
|
|
|
90
90
|
dependency = current_dependencies[current_spec.name]
|
|
91
91
|
groups = ""
|
|
92
92
|
if dependency && !options[:parseable]
|
|
93
|
-
groups = dependency.groups
|
|
93
|
+
groups = dependency.groups
|
|
94
|
+
groups = groups.sort if options_include_groups
|
|
95
|
+
groups = groups.join(", ")
|
|
94
96
|
end
|
|
95
97
|
|
|
96
98
|
outdated_gems << {
|
|
@@ -101,13 +103,11 @@ module Bundler
|
|
|
101
103
|
}
|
|
102
104
|
end
|
|
103
105
|
|
|
104
|
-
relevant_outdated_gems = if
|
|
105
|
-
outdated_gems.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
gems
|
|
110
|
-
end.compact
|
|
106
|
+
relevant_outdated_gems = if options[:groups]
|
|
107
|
+
without_groups, with_groups = outdated_gems.partition {|g| g[:groups].empty? }
|
|
108
|
+
with_groups.group_by {|g| g[:groups] }.sort.flat_map(&:last) + without_groups
|
|
109
|
+
elsif options_include_groups
|
|
110
|
+
outdated_gems.select {|g| g[:groups].split(", ").include?(options[:group]) }
|
|
111
111
|
else
|
|
112
112
|
outdated_gems
|
|
113
113
|
end
|
|
@@ -333,8 +333,6 @@ module Bundler
|
|
|
333
333
|
|
|
334
334
|
Bundler.ui.info justify(header, column_sizes)
|
|
335
335
|
|
|
336
|
-
data.sort_by! {|row| row[0] }
|
|
337
|
-
|
|
338
336
|
data.each do |row|
|
|
339
337
|
Bundler.ui.info justify(row, column_sizes)
|
|
340
338
|
end
|
data/lib/bundler/cli/platform.rb
CHANGED
|
@@ -25,7 +25,7 @@ module Bundler
|
|
|
25
25
|
else
|
|
26
26
|
platforms = Bundler.definition.platforms.map {|p| "* #{p}" }
|
|
27
27
|
|
|
28
|
-
output <<
|
|
28
|
+
output << platform_info
|
|
29
29
|
output << "Your app has gems that work on these platforms:\n#{platforms.join("\n")}"
|
|
30
30
|
|
|
31
31
|
if ruby_version
|
|
@@ -44,5 +44,19 @@ module Bundler
|
|
|
44
44
|
|
|
45
45
|
Bundler.ui.info output.join("\n\n")
|
|
46
46
|
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def platform_info
|
|
51
|
+
info = "Your platform is: #{Gem::Platform.local}"
|
|
52
|
+
return info if Bundler.local_platform == Gem::Platform.local
|
|
53
|
+
|
|
54
|
+
info + "\nHowever, your effective platform is: #{Bundler.local_platform} " \
|
|
55
|
+
"(because force_ruby_platform is #{force_ruby_platform_origin})"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def force_ruby_platform_origin
|
|
59
|
+
Bundler.settings.pretty_values_for(:force_ruby_platform).first.sub(/\ASet /, "set ")
|
|
60
|
+
end
|
|
47
61
|
end
|
|
48
62
|
end
|
data/lib/bundler/cli/show.rb
CHANGED
|
@@ -20,7 +20,7 @@ module Bundler
|
|
|
20
20
|
if gem_name == "bundler"
|
|
21
21
|
path = File.expand_path("../../..", __dir__)
|
|
22
22
|
else
|
|
23
|
-
spec =
|
|
23
|
+
spec = spec_for_gem(gem_name)
|
|
24
24
|
return unless spec
|
|
25
25
|
path = spec.full_gem_path
|
|
26
26
|
unless File.directory?(path)
|
|
@@ -55,6 +55,10 @@ module Bundler
|
|
|
55
55
|
|
|
56
56
|
private
|
|
57
57
|
|
|
58
|
+
def spec_for_gem(name)
|
|
59
|
+
Bundler::CLI::Common.select_spec_with_match_type(name, options)
|
|
60
|
+
end
|
|
61
|
+
|
|
58
62
|
def fetch_latest_specs
|
|
59
63
|
definition = Bundler.definition(true)
|
|
60
64
|
Bundler.ui.info "Fetching remote specs for outdated check...\n\n"
|
data/lib/bundler/cli/update.rb
CHANGED
|
@@ -13,7 +13,7 @@ module Bundler
|
|
|
13
13
|
|
|
14
14
|
update_bundler = options[:bundler]
|
|
15
15
|
|
|
16
|
-
Bundler.self_manager.update_bundler_and_restart_with_it_if_needed(update_bundler) if update_bundler
|
|
16
|
+
Bundler.self_manager.update_bundler_and_restart_with_it_if_needed(update_bundler, pre: options[:pre]) if update_bundler
|
|
17
17
|
|
|
18
18
|
sources = Array(options[:source])
|
|
19
19
|
groups = Array(options[:group]).map(&:to_sym)
|
data/lib/bundler/cli.rb
CHANGED
|
@@ -177,7 +177,7 @@ module Bundler
|
|
|
177
177
|
else
|
|
178
178
|
puts File.read("#{man_path}/#{File.basename(man_page)}.ronn")
|
|
179
179
|
end
|
|
180
|
-
elsif command_path =
|
|
180
|
+
elsif command_path = self.class.bundler_command_path(cli)
|
|
181
181
|
Kernel.exec(command_path, "--help")
|
|
182
182
|
else
|
|
183
183
|
super
|
|
@@ -189,11 +189,23 @@ module Bundler
|
|
|
189
189
|
return Bundler::Plugin.exec_command(command, ARGV[1..-1])
|
|
190
190
|
end
|
|
191
191
|
|
|
192
|
-
return super unless command_path =
|
|
192
|
+
return super unless command_path = bundler_command_path(command)
|
|
193
193
|
|
|
194
194
|
Kernel.exec(command_path, *ARGV[1..-1])
|
|
195
195
|
end
|
|
196
196
|
|
|
197
|
+
# Only PATH is searched, unlike Bundler.which, which also finds a file in
|
|
198
|
+
# the current directory and returns a bare name that Kernel.exec cannot run.
|
|
199
|
+
def self.bundler_command_path(command)
|
|
200
|
+
ENV.fetch("PATH", "").split(File::PATH_SEPARATOR).each do |path|
|
|
201
|
+
path = path[1..-2] if path.start_with?('"') && path.end_with?('"')
|
|
202
|
+
command_path = Bundler.find_executable(File.expand_path("bundler-#{command}", path))
|
|
203
|
+
return command_path if command_path
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
nil
|
|
207
|
+
end
|
|
208
|
+
|
|
197
209
|
desc "init [OPTIONS]", "Generates a Gemfile into the current working directory"
|
|
198
210
|
long_desc <<-D
|
|
199
211
|
Init generates a default Gemfile in the current working directory. When adding a
|
|
@@ -319,10 +331,10 @@ module Bundler
|
|
|
319
331
|
method_option "source", type: :array, banner: "Update a specific source (and all gems associated with it)"
|
|
320
332
|
method_option "force", type: :boolean, aliases: "--redownload", banner: "Force reinstalling every gem, even if already installed"
|
|
321
333
|
method_option "ruby", type: :boolean, banner: "Update ruby specified in Gemfile.lock"
|
|
322
|
-
method_option "bundler", type: :string, lazy_default: "
|
|
334
|
+
method_option "bundler", type: :string, lazy_default: ">= #{Bundler::VERSION}", banner: "Update the locked version of bundler"
|
|
323
335
|
method_option "patch", type: :boolean, banner: "Prefer updating only to next patch version"
|
|
324
336
|
method_option "minor", type: :boolean, banner: "Prefer updating only to next minor version"
|
|
325
|
-
method_option "major", type: :boolean, banner: "Prefer updating to
|
|
337
|
+
method_option "major", type: :boolean, banner: "Prefer updating to latest major version (default)"
|
|
326
338
|
method_option "pre", type: :boolean, banner: "Always choose the highest allowed version when updating gems, regardless of prerelease status"
|
|
327
339
|
method_option "strict", type: :boolean, banner: "Do not allow any gem to be updated past latest --patch | --minor | --major"
|
|
328
340
|
method_option "conservative", type: :boolean, banner: "Use bundle install conservative update behavior and do not allow shared dependencies to be updated."
|
|
@@ -342,6 +354,7 @@ module Bundler
|
|
|
342
354
|
D
|
|
343
355
|
method_option "paths", type: :boolean, banner: "List the paths of all gems that are required by your Gemfile."
|
|
344
356
|
method_option "outdated", type: :boolean, banner: "Show verbose output including whether gems are outdated (removed)."
|
|
357
|
+
method_option "exact-match", type: :boolean, banner: "Only match gems whose names exactly match the given name"
|
|
345
358
|
def show(gem_name = nil)
|
|
346
359
|
if ARGV.include?("--outdated")
|
|
347
360
|
removed_message = "the `--outdated` flag to `bundle show` has been removed in favor of `bundle show --verbose`"
|
|
@@ -367,6 +380,7 @@ module Bundler
|
|
|
367
380
|
desc "info GEM [OPTIONS]", "Show information for the given gem"
|
|
368
381
|
method_option "path", type: :boolean, banner: "Print full path to gem"
|
|
369
382
|
method_option "version", type: :boolean, banner: "Print gem version"
|
|
383
|
+
method_option "exact-match", type: :boolean, banner: "Only match gems whose names exactly match the given name"
|
|
370
384
|
def info(gem_name)
|
|
371
385
|
require_relative "cli/info"
|
|
372
386
|
Info.new(options, gem_name).run
|
|
@@ -434,7 +448,7 @@ module Bundler
|
|
|
434
448
|
method_option "filter-strict", type: :boolean, aliases: "--strict", banner: "Only list newer versions allowed by your Gemfile requirements"
|
|
435
449
|
method_option "update-strict", type: :boolean, banner: "Strict conservative resolution, do not allow any gem to be updated past latest --patch | --minor | --major"
|
|
436
450
|
method_option "minor", type: :boolean, banner: "Prefer updating only to next minor version"
|
|
437
|
-
method_option "major", type: :boolean, banner: "Prefer updating to
|
|
451
|
+
method_option "major", type: :boolean, banner: "Prefer updating to latest major version (default)"
|
|
438
452
|
method_option "patch", type: :boolean, banner: "Prefer updating only to next patch version"
|
|
439
453
|
method_option "filter-major", type: :boolean, banner: "Only list major newer versions"
|
|
440
454
|
method_option "filter-minor", type: :boolean, banner: "Only list minor newer versions"
|
|
@@ -530,6 +544,7 @@ module Bundler
|
|
|
530
544
|
|
|
531
545
|
desc "open GEM", "Opens the source directory of the given bundled gem"
|
|
532
546
|
method_option "path", type: :string, lazy_default: "", banner: "Open relative path of the gem source."
|
|
547
|
+
method_option "exact-match", type: :boolean, banner: "Only match gems whose names exactly match the given name"
|
|
533
548
|
def open(name)
|
|
534
549
|
require_relative "cli/open"
|
|
535
550
|
Open.new(options, name).run
|
|
@@ -640,11 +655,11 @@ module Bundler
|
|
|
640
655
|
method_option "normalize-platforms", type: :boolean, default: false, banner: "Normalize lockfile platforms"
|
|
641
656
|
method_option "patch", type: :boolean, banner: "If updating, prefer updating only to next patch version"
|
|
642
657
|
method_option "minor", type: :boolean, banner: "If updating, prefer updating only to next minor version"
|
|
643
|
-
method_option "major", type: :boolean, banner: "If updating, prefer updating to
|
|
658
|
+
method_option "major", type: :boolean, banner: "If updating, prefer updating to latest major version (default)"
|
|
644
659
|
method_option "pre", type: :boolean, banner: "If updating, always choose the highest allowed version, regardless of prerelease status"
|
|
645
660
|
method_option "strict", type: :boolean, banner: "If updating, do not allow any gem to be updated past latest --patch | --minor | --major"
|
|
646
661
|
method_option "conservative", type: :boolean, banner: "If updating, use bundle install conservative update behavior and do not allow shared dependencies to be updated"
|
|
647
|
-
method_option "bundler", type: :string, lazy_default: "
|
|
662
|
+
method_option "bundler", type: :string, lazy_default: ">= #{Bundler::VERSION}", banner: "Update the locked version of bundler"
|
|
648
663
|
method_option "cooldown", type: :numeric, banner: "Only consider gem versions published at least N days ago. Use 0 to disable."
|
|
649
664
|
def lock
|
|
650
665
|
require_relative "cli/lock"
|
data/lib/bundler/constants.rb
CHANGED
data/lib/bundler/definition.rb
CHANGED
|
@@ -198,7 +198,7 @@ module Bundler
|
|
|
198
198
|
|
|
199
199
|
sources.cached!
|
|
200
200
|
|
|
201
|
-
if options[:add_checksums] || (!options[:local] && (install_needed? || refetch_needed?(options)))
|
|
201
|
+
if options[:add_checksums] || (!options[:local] && (install_needed? || refetch_needed?(options) || @locked_spec_with_empty_checksums))
|
|
202
202
|
sources.remote!
|
|
203
203
|
true
|
|
204
204
|
else
|
|
@@ -346,7 +346,9 @@ module Bundler
|
|
|
346
346
|
#
|
|
347
347
|
# @return [SpecSet] resolved dependencies
|
|
348
348
|
def resolve
|
|
349
|
-
@resolve
|
|
349
|
+
return @resolve if @resolve
|
|
350
|
+
|
|
351
|
+
@resolve = if Bundler.frozen_bundle?
|
|
350
352
|
Bundler.ui.debug "Frozen, using resolution from the lockfile"
|
|
351
353
|
@locked_specs
|
|
352
354
|
elsif no_resolve_needed?
|
|
@@ -366,6 +368,8 @@ module Bundler
|
|
|
366
368
|
|
|
367
369
|
start_resolution
|
|
368
370
|
end
|
|
371
|
+
warn_inert_overrides(@resolve)
|
|
372
|
+
@resolve
|
|
369
373
|
end
|
|
370
374
|
|
|
371
375
|
def spec_git_paths
|
|
@@ -650,7 +654,7 @@ module Bundler
|
|
|
650
654
|
@missing_lockfile_dep ||
|
|
651
655
|
@unlocking_bundler ||
|
|
652
656
|
@locked_spec_with_missing_checksums ||
|
|
653
|
-
|
|
657
|
+
empty_checksums_actionable? ||
|
|
654
658
|
@locked_spec_with_missing_deps ||
|
|
655
659
|
@locked_spec_with_invalid_deps
|
|
656
660
|
end
|
|
@@ -659,6 +663,16 @@ module Bundler
|
|
|
659
663
|
unlocking? || something_changed?
|
|
660
664
|
end
|
|
661
665
|
|
|
666
|
+
# Only a remote fetch can fill an empty CHECKSUMS entry, so it justifies a
|
|
667
|
+
# resolution only when one is coming. Resolving locally for it would repeat
|
|
668
|
+
# on every `Bundler.setup` without changing the lockfile. Frozen mode still
|
|
669
|
+
# has to refuse the entry.
|
|
670
|
+
def empty_checksums_actionable?
|
|
671
|
+
return false unless @locked_spec_with_empty_checksums
|
|
672
|
+
|
|
673
|
+
Bundler.frozen_bundle? || !sources.local_mode?
|
|
674
|
+
end
|
|
675
|
+
|
|
662
676
|
def should_add_extra_platforms?
|
|
663
677
|
!lockfile_exists? && Bundler::MatchPlatform.generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform]
|
|
664
678
|
end
|
|
@@ -1095,25 +1109,61 @@ module Bundler
|
|
|
1095
1109
|
end
|
|
1096
1110
|
|
|
1097
1111
|
converge_overrides_outside_dependencies
|
|
1112
|
+
converge_rewritten_dependencies
|
|
1098
1113
|
|
|
1099
1114
|
@changed_dependencies.any?
|
|
1100
1115
|
end
|
|
1101
1116
|
|
|
1102
|
-
|
|
1117
|
+
# The lockfile keeps the upstream dependencies of every gem, so a gem that
|
|
1118
|
+
# a `from:`/`to:` override cut loose stays locked until a resolution drops
|
|
1119
|
+
# it.
|
|
1120
|
+
def converge_rewritten_dependencies
|
|
1103
1121
|
@overrides.each do |override|
|
|
1104
|
-
|
|
1105
|
-
# fresh resolution (no lockfile) or when the user runs `bundle update`.
|
|
1106
|
-
# Forcing a full re-resolve from a single :all directive would surprise
|
|
1107
|
-
# users with unrelated dependency churn.
|
|
1108
|
-
next unless override.target.is_a?(String)
|
|
1122
|
+
next unless override.from
|
|
1109
1123
|
|
|
1110
1124
|
name = override.target
|
|
1111
|
-
next if @changed_dependencies.include?(name)
|
|
1112
1125
|
next if @originally_locked_specs[name].empty?
|
|
1113
|
-
|
|
1126
|
+
next if @dependencies.any? {|d| d.name == name }
|
|
1127
|
+
|
|
1128
|
+
still_required = @originally_locked_specs.any? do |s|
|
|
1129
|
+
Override.rewrite_dependencies(@overrides, s.name, s.runtime_dependencies).any? {|d| d.name == name }
|
|
1130
|
+
end
|
|
1131
|
+
next if still_required
|
|
1132
|
+
|
|
1133
|
+
@gems_to_unlock << name
|
|
1134
|
+
@changed_dependencies << name
|
|
1135
|
+
end
|
|
1136
|
+
end
|
|
1137
|
+
|
|
1138
|
+
# A misspelled `from:` gem leaves the override with nothing to rewrite.
|
|
1139
|
+
def warn_inert_overrides(specs)
|
|
1140
|
+
@overrides.each do |override|
|
|
1141
|
+
next unless override.from
|
|
1142
|
+
next if specs[override.from].any? {|s| s.dependencies.any? {|d| d.name == override.target } }
|
|
1143
|
+
|
|
1144
|
+
Bundler.ui.warn "#{override} has no effect because the bundle has no #{override.from} that depends on #{override.target}"
|
|
1145
|
+
end
|
|
1146
|
+
end
|
|
1147
|
+
|
|
1148
|
+
def converge_overrides_outside_dependencies
|
|
1149
|
+
@overrides.each do |override|
|
|
1150
|
+
# :all and metadata overrides are intentionally not pre-unlocked. The
|
|
1151
|
+
# lockfile does not record overrides, so unlocking for them would
|
|
1152
|
+
# re-resolve on every run and reject every frozen install. Install-time
|
|
1153
|
+
# compatibility checks already honor them for locked specs, and they
|
|
1154
|
+
# affect resolution on a fresh lock or when the user runs `bundle update`.
|
|
1155
|
+
next unless override.target.is_a?(String) && override.field == :version
|
|
1156
|
+
|
|
1157
|
+
name = override.target
|
|
1158
|
+
# Overrides on direct deps are detected in the per-dep
|
|
1114
1159
|
# converge_dependencies loop via apply_override_to + matches_spec?.
|
|
1115
|
-
|
|
1116
|
-
|
|
1160
|
+
next if @dependencies.any? {|d| d.name == name }
|
|
1161
|
+
|
|
1162
|
+
locked_specs = @originally_locked_specs[name]
|
|
1163
|
+
next if locked_specs.empty?
|
|
1164
|
+
# Only a version string constrains on its own. :ignore_upper and nil
|
|
1165
|
+
# loosen requirements the lockfile already satisfies.
|
|
1166
|
+
next if override.apply_to(Gem::Requirement.default).satisfied_by?(locked_specs.first.version)
|
|
1117
1167
|
|
|
1118
1168
|
@gems_to_unlock << name
|
|
1119
1169
|
@changed_dependencies << name
|
|
@@ -1342,7 +1392,7 @@ module Bundler
|
|
|
1342
1392
|
end
|
|
1343
1393
|
|
|
1344
1394
|
def source_map
|
|
1345
|
-
@source_map ||= SourceMap.new(sources, dependencies, @locked_specs)
|
|
1395
|
+
@source_map ||= SourceMap.new(sources, dependencies, @locked_specs, @overrides.filter_map {|o| o.operation if o.from })
|
|
1346
1396
|
end
|
|
1347
1397
|
|
|
1348
1398
|
def new_resolver_for_full_update
|
data/lib/bundler/dsl.rb
CHANGED
|
@@ -17,7 +17,7 @@ module Bundler
|
|
|
17
17
|
VALID_PLATFORMS = Bundler::CurrentRuby::PLATFORM_MAP.keys.freeze
|
|
18
18
|
|
|
19
19
|
VALID_KEYS = %w[group groups git path glob name branch ref tag require submodules
|
|
20
|
-
platform platforms source install_if force_ruby_platform].freeze
|
|
20
|
+
platform platforms source install_if force_ruby_platform sparse_checkout].freeze
|
|
21
21
|
|
|
22
22
|
GITHUB_PULL_REQUEST_URL = %r{\Ahttps://github\.com/([A-Za-z0-9_\-\.]+/[A-Za-z0-9_\-\.]+)/pull/(\d+)\z}
|
|
23
23
|
GITLAB_MERGE_REQUEST_URL = %r{\Ahttps://gitlab\.com/([A-Za-z0-9_\-\./]+)/-/merge_requests/(\d+)\z}
|
|
@@ -200,6 +200,12 @@ module Bundler
|
|
|
200
200
|
|
|
201
201
|
def override(target, **operations)
|
|
202
202
|
validate_override_target!(target)
|
|
203
|
+
source_location = caller_locations(1, 1)&.first
|
|
204
|
+
|
|
205
|
+
if operations.key?(:from) || operations.key?(:to)
|
|
206
|
+
add_dependency_override(target, operations, source_location)
|
|
207
|
+
return
|
|
208
|
+
end
|
|
203
209
|
|
|
204
210
|
if target == :all && operations.key?(:version)
|
|
205
211
|
raise ArgumentError, "`override :all, version:` is not allowed; version requirements are per-gem"
|
|
@@ -211,7 +217,6 @@ module Bundler
|
|
|
211
217
|
validate_override_uniqueness!(target, field)
|
|
212
218
|
end
|
|
213
219
|
|
|
214
|
-
source_location = caller_locations(1, 1)&.first
|
|
215
220
|
operations.each do |field, operation|
|
|
216
221
|
@overrides << Override.new(target, field, operation, source_location: source_location)
|
|
217
222
|
end
|
|
@@ -219,6 +224,7 @@ module Bundler
|
|
|
219
224
|
|
|
220
225
|
def to_definition(lockfile, unlock)
|
|
221
226
|
check_primary_source_safety
|
|
227
|
+
check_dropped_dependencies
|
|
222
228
|
lockfile = @lockfile unless @lockfile.nil?
|
|
223
229
|
Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version, @optional_groups, @gemfiles, @overrides)
|
|
224
230
|
end
|
|
@@ -317,6 +323,54 @@ module Bundler
|
|
|
317
323
|
raise ArgumentError, "duplicate override for #{target.inspect} `#{field}:`"
|
|
318
324
|
end
|
|
319
325
|
|
|
326
|
+
def add_dependency_override(target, operations, source_location)
|
|
327
|
+
unless operations.key?(:from)
|
|
328
|
+
raise ArgumentError, "`override #{target.inspect}, to:` requires `from:` naming the gem whose dependency is rewritten"
|
|
329
|
+
end
|
|
330
|
+
unless operations.key?(:to)
|
|
331
|
+
raise ArgumentError, "`override #{target.inspect}, from:` requires `to:`; use `to: nil` to drop the dependency or `to: \"<gem>\"` to replace it"
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
from = operations[:from]
|
|
335
|
+
to = operations[:to]
|
|
336
|
+
requirement = operations[:version]
|
|
337
|
+
|
|
338
|
+
raise ArgumentError, "`override :all` does not accept `from:`" if target == :all
|
|
339
|
+
raise ArgumentError, "`from:` must be a gem name string, got #{from.inspect}" unless from.is_a?(String)
|
|
340
|
+
raise ArgumentError, "`to:` must be a gem name string or nil, got #{to.inspect}" unless to.nil? || to.is_a?(String)
|
|
341
|
+
raise ArgumentError, "`to:` must name a gem other than #{target.inspect} and #{from.inspect}" if to == target || to == from
|
|
342
|
+
validate_gem_name!(from)
|
|
343
|
+
validate_gem_name!(to) if to
|
|
344
|
+
|
|
345
|
+
unsupported = operations.keys - [:from, :to, :version]
|
|
346
|
+
if unsupported.any?
|
|
347
|
+
raise ArgumentError, "unsupported override field `#{unsupported.first}:` with `from:`; supported fields: `to:`, `version:`"
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
if operations.key?(:version)
|
|
351
|
+
raise ArgumentError, "`version:` with `from:` requires `to:` to name a replacement gem" if to.nil?
|
|
352
|
+
raise ArgumentError, "`version:` with `from:` must be a version requirement string, got #{requirement.inspect}" unless requirement.is_a?(String)
|
|
353
|
+
validate_override_operation!(requirement)
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
if @overrides.any? {|o| o.target == target && o.from == from }
|
|
357
|
+
raise ArgumentError, "duplicate override for #{target.inspect} `from: #{from.inspect}`"
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
@overrides << Override.new(target, :to, to, from: from, requirement: requirement, source_location: source_location)
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
# Dropping a gem the Gemfile requires directly would leave it installed
|
|
364
|
+
# anyway, with only the parent's requirement gone.
|
|
365
|
+
def check_dropped_dependencies
|
|
366
|
+
@overrides.each do |override|
|
|
367
|
+
next unless override.from && override.operation.nil?
|
|
368
|
+
next unless @dependencies.any? {|d| d.name == override.target }
|
|
369
|
+
|
|
370
|
+
raise GemfileError, "#{override} cannot drop #{override.target} because the Gemfile depends on it directly"
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
|
|
320
374
|
def add_dependency(name, version = nil, options = {})
|
|
321
375
|
options["gemfile"] = @gemfile
|
|
322
376
|
options["source"] ||= @source
|
|
@@ -460,7 +514,7 @@ module Bundler
|
|
|
460
514
|
@valid_keys ||= VALID_KEYS
|
|
461
515
|
end
|
|
462
516
|
|
|
463
|
-
def
|
|
517
|
+
def validate_gem_name!(name)
|
|
464
518
|
if name.is_a?(Symbol)
|
|
465
519
|
raise GemfileError, %(You need to specify gem names as Strings. Use 'gem "#{name}"' instead)
|
|
466
520
|
end
|
|
@@ -468,6 +522,10 @@ module Bundler
|
|
|
468
522
|
raise GemfileError, %('#{name}' is not a valid gem name because it contains whitespace)
|
|
469
523
|
end
|
|
470
524
|
raise GemfileError, %(an empty gem name is not valid) if name.empty?
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
def normalize_options(name, version, opts)
|
|
528
|
+
validate_gem_name!(name)
|
|
471
529
|
|
|
472
530
|
normalize_hash(opts)
|
|
473
531
|
|
|
@@ -56,9 +56,13 @@ module Bundler
|
|
|
56
56
|
if https?(uri) && !https?(new_uri)
|
|
57
57
|
raise HTTPError, "Redirecting to a non-https URI is not allowed: #{URICredentialsFilter.credential_filtered_uri(new_uri)}"
|
|
58
58
|
end
|
|
59
|
-
if new_uri.host == uri.host
|
|
59
|
+
if [new_uri.scheme, new_uri.host, new_uri.port] == [uri.scheme, uri.host, uri.port]
|
|
60
60
|
new_uri.user = uri.user
|
|
61
61
|
new_uri.password = uri.password
|
|
62
|
+
else
|
|
63
|
+
# see Gem::RemoteFetcher#fetch_http. A nil value removes the header
|
|
64
|
+
# that ConnectionPools adds from its override_headers.
|
|
65
|
+
headers = headers.merge("X-Gemfile-Source" => nil)
|
|
62
66
|
end
|
|
63
67
|
fetch(new_uri, headers, counter + 1)
|
|
64
68
|
when Gem::Net::HTTPRequestedRangeNotSatisfiable
|
data/lib/bundler/gem_helper.rb
CHANGED
|
@@ -69,7 +69,8 @@ module Bundler
|
|
|
69
69
|
@specs = all_specs.map {|s| SpecInstallation.new(s) }
|
|
70
70
|
specs_by_name = @specs.to_h {|s| [s.name, s] }
|
|
71
71
|
@specs.each do |spec_install|
|
|
72
|
-
|
|
72
|
+
dependencies = Override.rewrite_dependencies(installer.definition.overrides, spec_install.name, spec_install.spec.dependencies)
|
|
73
|
+
spec_install.dependencies = dependencies.filter_map do |dep|
|
|
73
74
|
specs_by_name[dep.name] unless dep.type == :development || dep.name == spec_install.name
|
|
74
75
|
end
|
|
75
76
|
end
|
data/lib/bundler/installer.rb
CHANGED
|
@@ -103,7 +103,7 @@ module Bundler
|
|
|
103
103
|
|
|
104
104
|
if options[:binstubs_cmd] && spec.executables.empty?
|
|
105
105
|
options = {}
|
|
106
|
-
spec.runtime_dependencies.each do |dep|
|
|
106
|
+
Override.rewrite_dependencies(@definition.overrides, spec.name, spec.runtime_dependencies).each do |dep|
|
|
107
107
|
bins = @definition.specs[dep].first.executables
|
|
108
108
|
options[dep.name] = bins unless bins.empty?
|
|
109
109
|
end
|
|
@@ -127,6 +127,8 @@ module Bundler
|
|
|
127
127
|
template_path = File.expand_path("templates/Executable", __dir__)
|
|
128
128
|
template = File.read(template_path)
|
|
129
129
|
|
|
130
|
+
Bundler.mkdir_p(bin_path)
|
|
131
|
+
|
|
130
132
|
exists = []
|
|
131
133
|
spec.executables.each do |executable|
|
|
132
134
|
binstub_path = "#{bin_path}/#{executable}"
|
|
@@ -173,6 +175,8 @@ module Bundler
|
|
|
173
175
|
ruby_command = Thor::Util.ruby_command
|
|
174
176
|
ruby_command = ruby_command
|
|
175
177
|
|
|
178
|
+
Bundler.mkdir_p(bin_path)
|
|
179
|
+
|
|
176
180
|
spec.executables.each do |executable|
|
|
177
181
|
next if executable == "bundle"
|
|
178
182
|
executable_path = Pathname(spec.full_gem_path).join(spec.bindir, executable).relative_path_from(bin_path)
|
|
@@ -286,7 +286,7 @@ module Bundler
|
|
|
286
286
|
# which would affect `bundler/setup` performance.
|
|
287
287
|
def validate_dependencies(spec)
|
|
288
288
|
if !@materialization_options[:strict] && spec.is_a?(StubSpecification)
|
|
289
|
-
spec.dependencies = dependencies
|
|
289
|
+
spec.dependencies = Override.rewrite_dependencies(overrides, name, dependencies)
|
|
290
290
|
else
|
|
291
291
|
if !source.is_a?(Source::Path) && spec.runtime_dependencies.sort != dependencies.sort
|
|
292
292
|
raise IncorrectLockfileDependencies.new(self, spec.runtime_dependencies, dependencies)
|