rubygems-update 4.1.0.beta2 → 4.1.0.beta3
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/CHANGELOG.md +53 -0
- data/Manifest.txt +1 -1
- data/lib/bundler/build_metadata.rb +2 -2
- data/lib/bundler/cli/lock.rb +5 -1
- data/lib/bundler/definition.rb +45 -9
- data/lib/bundler/dsl.rb +34 -21
- data/lib/bundler/fetcher/downloader.rb +9 -3
- data/lib/bundler/fetcher.rb +4 -1
- data/lib/bundler/lockfile_generator.rb +6 -0
- data/lib/bundler/lockfile_parser.rb +17 -1
- data/lib/bundler/man/gemfile.5 +18 -9
- data/lib/bundler/man/gemfile.5.ronn +28 -14
- data/lib/bundler/match_platform.rb +12 -3
- data/lib/bundler/override.rb +60 -7
- data/lib/bundler/resolver.rb +1 -1
- data/lib/bundler/rubygems_ext.rb +15 -4
- data/lib/bundler/source/rubygems.rb +2 -2
- data/lib/bundler/source_map.rb +1 -1
- data/lib/bundler/vendor/fileutils/lib/fileutils.rb +54 -29
- data/lib/bundler/version.rb +1 -1
- data/lib/rubygems/compact_index_client/parser.rb +1 -0
- data/lib/rubygems/ext/builder.rb +7 -3
- data/lib/rubygems/specification_policy.rb +12 -10
- data/lib/rubygems/uninstaller.rb +14 -2
- data/lib/rubygems/user_interaction.rb +6 -9
- data/lib/rubygems/vendor/net-http/lib/net/http/generic_request.rb +10 -1
- data/lib/rubygems/vendor/net-http/lib/net/http/header.rb +56 -15
- data/lib/rubygems/vendor/net-http/lib/net/http/request.rb +1 -0
- data/lib/rubygems/vendor/net-http/lib/net/http/requests.rb +59 -24
- data/lib/rubygems/vendor/net-http/lib/net/http/response.rb +40 -15
- data/lib/rubygems/vendor/net-http/lib/net/http.rb +73 -14
- data/lib/rubygems/vendor/net-protocol/COPYING +56 -0
- data/lib/rubygems/vendor/net-protocol/lib/net/protocol.rb +95 -26
- data/lib/rubygems/vendor/uri/lib/uri/common.rb +1 -1
- data/lib/rubygems/vendor/uri/lib/uri/generic.rb +15 -3
- data/lib/rubygems/vendor/uri/lib/uri/version.rb +1 -1
- data/lib/rubygems/yaml_serializer.rb +131 -103
- data/lib/rubygems.rb +23 -7
- metadata +3 -3
- data/lib/rubygems/vendor/net-protocol/LICENSE.txt +0 -22
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6318a5162408d17e02ca7534ba15f8701fe7eeeeaf7d891f4331588d0e595472
|
|
4
|
+
data.tar.gz: c044abf170bb96482454ed885860c11aa96cda0618cdaac5177009bdbb1d814d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3c0e7401e36950ef3563213d1489dacccf2cdabf370c63bdb789a0ac0f0bd68987d3ac558dcb9054bbd9dc6ab0003853878d4563f43a43fb995d77d6ecfd6ddb
|
|
7
|
+
data.tar.gz: 0677d5d8ec93ba1e7d6698c7b480d5f496cc2d42a37aea380e981133da66ef3b49bece38b90aab61425a30c5b7126e6f2354eea48614b508ec6ac72e6225e856
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,59 @@
|
|
|
2
2
|
|
|
3
3
|
Bundler's changelog before 4.0.0, when it was versioned separately from RubyGems, is in [doc/CHANGELOG-bundler-2.x.md](https://github.com/ruby/rubygems/blob/master/doc/CHANGELOG-bundler-2.x.md).
|
|
4
4
|
|
|
5
|
+
## 4.1.0.beta3 / 2026-10-28
|
|
6
|
+
|
|
7
|
+
### RubyGems
|
|
8
|
+
|
|
9
|
+
#### Enhancements:
|
|
10
|
+
|
|
11
|
+
* Installs bundler 4.1.0.beta3 as a default gem.
|
|
12
|
+
|
|
13
|
+
#### Bug fixes:
|
|
14
|
+
|
|
15
|
+
* Skip executable removal gracefully when the bin directory is missing. Pull request [#9963](https://github.com/ruby/rubygems/pull/9963) by Evan Li and Hiroshi SHIBATA
|
|
16
|
+
* Fix file locks letting multiple processes in when lock files are removed. Pull request [#9930](https://github.com/ruby/rubygems/pull/9930) by Richard Janita and Hiroshi SHIBATA
|
|
17
|
+
* Turn off echo before printing the password prompt. Pull request [#9969](https://github.com/ruby/rubygems/pull/9969) by Mike Dalessio
|
|
18
|
+
|
|
19
|
+
### Bundler
|
|
20
|
+
|
|
21
|
+
Changes already released in 4.0.x are not repeated here.
|
|
22
|
+
|
|
23
|
+
#### Features:
|
|
24
|
+
|
|
25
|
+
* Rename the `from:` and `to:` keys of `override` to `in:` and `with:`. Pull request [#9979](https://github.com/ruby/rubygems/pull/9979) by Hiroshi SHIBATA
|
|
26
|
+
* Record overrides in Gemfile.lock (`OVERRIDES` section). Pull request [#9958](https://github.com/ruby/rubygems/pull/9958) by Ufuk Kayserilioglu
|
|
27
|
+
|
|
28
|
+
#### Bug fixes:
|
|
29
|
+
|
|
30
|
+
* Make `Bundler::Source::Rubygems#hash` agree with `eql?`. Pull request [#9983](https://github.com/ruby/rubygems/pull/9983) by Hiroshi SHIBATA
|
|
31
|
+
* Add checksums after platform changes in `bundle lock`. Pull request [#9960](https://github.com/ruby/rubygems/pull/9960) by Farid Zakaria
|
|
32
|
+
* Apply BUNDLE_RETRY to lazy gemspec downloads. Pull request [#9868](https://github.com/ruby/rubygems/pull/9868) by Islam Elsayed
|
|
33
|
+
* Fix file locks letting multiple processes in when lock files are removed. Pull request [#9930](https://github.com/ruby/rubygems/pull/9930) by Richard Janita and Hiroshi SHIBATA
|
|
34
|
+
* Preload git sources that share a cache one after another. Pull request [#9951](https://github.com/ruby/rubygems/pull/9951) by Shai
|
|
35
|
+
|
|
36
|
+
## 4.0.23 / 2026-10-14
|
|
37
|
+
|
|
38
|
+
### RubyGems
|
|
39
|
+
|
|
40
|
+
#### Enhancements:
|
|
41
|
+
|
|
42
|
+
* Update vendored gems to latest versions. Pull request [#9948](https://github.com/ruby/rubygems/pull/9948) by Hiroshi SHIBATA
|
|
43
|
+
* Drop setuid, setgid and sticky bits when extracting gems. Pull request [#9929](https://github.com/ruby/rubygems/pull/9929) by Hiroshi SHIBATA
|
|
44
|
+
* Improve handling of paths with invalid Windows characters. Pull request [#9276](https://github.com/ruby/rubygems/pull/9276) by Said Kaldybaev and Hiroshi SHIBATA
|
|
45
|
+
* Installs bundler 4.0.23 as a default gem.
|
|
46
|
+
|
|
47
|
+
### Bundler
|
|
48
|
+
|
|
49
|
+
#### Enhancements:
|
|
50
|
+
|
|
51
|
+
* Update vendored gems to latest versions. Pull request [#9948](https://github.com/ruby/rubygems/pull/9948) by Hiroshi SHIBATA
|
|
52
|
+
|
|
53
|
+
#### Bug fixes:
|
|
54
|
+
|
|
55
|
+
* Stop retrying a 416 response to a request without Range. Pull request [#9938](https://github.com/ruby/rubygems/pull/9938) by Hiroshi SHIBATA
|
|
56
|
+
* Respect Gemfile lockfile in `bundle lock`. Pull request [#9661](https://github.com/ruby/rubygems/pull/9661) by David Stosik and Hiroshi SHIBATA
|
|
57
|
+
|
|
5
58
|
## 4.1.0.beta2 / 2026-10-08
|
|
6
59
|
|
|
7
60
|
### RubyGems
|
data/Manifest.txt
CHANGED
|
@@ -503,7 +503,7 @@ lib/rubygems/vendor/net-http/lib/net/http/response.rb
|
|
|
503
503
|
lib/rubygems/vendor/net-http/lib/net/http/responses.rb
|
|
504
504
|
lib/rubygems/vendor/net-http/lib/net/http/status.rb
|
|
505
505
|
lib/rubygems/vendor/net-http/lib/net/https.rb
|
|
506
|
-
lib/rubygems/vendor/net-protocol/
|
|
506
|
+
lib/rubygems/vendor/net-protocol/COPYING
|
|
507
507
|
lib/rubygems/vendor/net-protocol/lib/net/protocol.rb
|
|
508
508
|
lib/rubygems/vendor/optparse/COPYING
|
|
509
509
|
lib/rubygems/vendor/optparse/lib/optionparser.rb
|
|
@@ -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-10-
|
|
8
|
-
@git_commit_sha = "
|
|
7
|
+
@built_at = "2026-10-28".freeze
|
|
8
|
+
@git_commit_sha = "cd7536a".freeze
|
|
9
9
|
# end ivars
|
|
10
10
|
|
|
11
11
|
# A hash representation of the build metadata.
|
data/lib/bundler/cli/lock.rb
CHANGED
|
@@ -42,7 +42,6 @@ module Bundler
|
|
|
42
42
|
|
|
43
43
|
Bundler.settings.temporary(frozen: false) do
|
|
44
44
|
definition = Bundler.definition(update, Bundler.default_lockfile)
|
|
45
|
-
definition.add_checksums if options["add-checksums"]
|
|
46
45
|
|
|
47
46
|
Bundler::CLI::Common.configure_gem_version_promoter(definition, options) if options[:update]
|
|
48
47
|
|
|
@@ -64,6 +63,11 @@ module Bundler
|
|
|
64
63
|
raise InvalidOption, "Removing all platforms from the bundle is not allowed"
|
|
65
64
|
end
|
|
66
65
|
|
|
66
|
+
# Adding checksums resolves the bundle to fetch them, so it has to
|
|
67
|
+
# run after every platform change above has been recorded, or the
|
|
68
|
+
# new platforms are listed in the lockfile without their specs.
|
|
69
|
+
definition.add_checksums if options["add-checksums"]
|
|
70
|
+
|
|
67
71
|
definition.remotely! unless options[:local]
|
|
68
72
|
|
|
69
73
|
if options["normalize-platforms"]
|
data/lib/bundler/definition.rb
CHANGED
|
@@ -167,6 +167,7 @@ module Bundler
|
|
|
167
167
|
|
|
168
168
|
@dependency_changes = converge_dependencies
|
|
169
169
|
@local_changes = converge_locals
|
|
170
|
+
@override_changes = converge_overrides
|
|
170
171
|
|
|
171
172
|
check_lockfile
|
|
172
173
|
end
|
|
@@ -477,6 +478,11 @@ module Bundler
|
|
|
477
478
|
@resolved_bundler_version || Bundler.gem_version
|
|
478
479
|
end
|
|
479
480
|
|
|
481
|
+
# The lines for the OVERRIDES section of Gemfile.lock.
|
|
482
|
+
def overrides_to_lock
|
|
483
|
+
@overrides.map(&:to_lock).uniq
|
|
484
|
+
end
|
|
485
|
+
|
|
480
486
|
def to_lock
|
|
481
487
|
require_relative "lockfile_generator"
|
|
482
488
|
LockfileGenerator.generate(self)
|
|
@@ -599,6 +605,11 @@ module Bundler
|
|
|
599
605
|
added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
|
|
600
606
|
deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } if deleted_deps.any?
|
|
601
607
|
|
|
608
|
+
if @override_changes
|
|
609
|
+
added.concat((overrides_to_lock - locked_overrides_to_lock).sort.map {|o| "* override #{o}" })
|
|
610
|
+
deleted.concat((locked_overrides_to_lock - overrides_to_lock).sort.map {|o| "* override #{o}" })
|
|
611
|
+
end
|
|
612
|
+
|
|
602
613
|
both_sources = Hash.new {|h, k| h[k] = [] }
|
|
603
614
|
current_dependencies.each {|d| both_sources[d.name][0] = d }
|
|
604
615
|
current_locked_dependencies.each {|d| both_sources[d.name][1] = d }
|
|
@@ -908,6 +919,8 @@ module Bundler
|
|
|
908
919
|
else
|
|
909
920
|
lockfile_changed_reason
|
|
910
921
|
end
|
|
922
|
+
elsif @override_changes
|
|
923
|
+
"the overrides in your gemfile changed"
|
|
911
924
|
else
|
|
912
925
|
"some dependencies were deleted from your gemfile"
|
|
913
926
|
end
|
|
@@ -943,6 +956,7 @@ module Bundler
|
|
|
943
956
|
[@locked_spec_with_empty_checksums, "your lockfile has an empty CHECKSUMS entry for \"#{@locked_spec_with_empty_checksums}\""],
|
|
944
957
|
[@locked_spec_with_missing_deps, "your lockfile includes \"#{@locked_spec_with_missing_deps}\" but not some of its dependencies"],
|
|
945
958
|
[@locked_spec_with_invalid_deps, "your lockfile does not satisfy dependencies of \"#{@locked_spec_with_invalid_deps}\""],
|
|
959
|
+
[@override_changes, "the overrides in your gemfile changed"],
|
|
946
960
|
].select(&:first).map(&:last).join(", ")
|
|
947
961
|
end
|
|
948
962
|
|
|
@@ -1115,7 +1129,7 @@ module Bundler
|
|
|
1115
1129
|
end
|
|
1116
1130
|
|
|
1117
1131
|
# The lockfile keeps the upstream dependencies of every gem, so a gem that
|
|
1118
|
-
# a `
|
|
1132
|
+
# a `with:`/`in:` override cut loose stays locked until a resolution drops
|
|
1119
1133
|
# it.
|
|
1120
1134
|
def converge_rewritten_dependencies
|
|
1121
1135
|
@overrides.each do |override|
|
|
@@ -1135,7 +1149,7 @@ module Bundler
|
|
|
1135
1149
|
end
|
|
1136
1150
|
end
|
|
1137
1151
|
|
|
1138
|
-
# A misspelled `
|
|
1152
|
+
# A misspelled `in:` gem leaves the override with nothing to rewrite.
|
|
1139
1153
|
def warn_inert_overrides(specs)
|
|
1140
1154
|
@overrides.each do |override|
|
|
1141
1155
|
next unless override.from
|
|
@@ -1145,13 +1159,29 @@ module Bundler
|
|
|
1145
1159
|
end
|
|
1146
1160
|
end
|
|
1147
1161
|
|
|
1162
|
+
# The lockfile records the Gemfile's overrides, so a change to them is a
|
|
1163
|
+
# change to the lockfile even when every locked version still satisfies
|
|
1164
|
+
# them. Rewriting the section needs no resolution, so this stays out of
|
|
1165
|
+
# #something_changed?. #write_lock rewrites it because the generated
|
|
1166
|
+
# contents differ, and the frozen check reports it.
|
|
1167
|
+
def converge_overrides
|
|
1168
|
+
return false unless @locked_gems
|
|
1169
|
+
|
|
1170
|
+
overrides_to_lock.sort != locked_overrides_to_lock.sort
|
|
1171
|
+
end
|
|
1172
|
+
|
|
1173
|
+
def locked_overrides_to_lock
|
|
1174
|
+
Array(@locked_gems&.overrides).map(&:to_lock).uniq
|
|
1175
|
+
end
|
|
1176
|
+
|
|
1148
1177
|
def converge_overrides_outside_dependencies
|
|
1149
1178
|
@overrides.each do |override|
|
|
1150
|
-
# :all and metadata overrides are intentionally not pre-unlocked.
|
|
1151
|
-
#
|
|
1152
|
-
#
|
|
1153
|
-
#
|
|
1154
|
-
#
|
|
1179
|
+
# :all and metadata overrides are intentionally not pre-unlocked.
|
|
1180
|
+
# Unlocking for them would re-resolve gems the user did not ask to
|
|
1181
|
+
# move. Install-time compatibility checks already honor them for locked
|
|
1182
|
+
# specs, and they affect resolution on a fresh lock or when the user
|
|
1183
|
+
# runs `bundle update`. Changing one still rewrites the OVERRIDES
|
|
1184
|
+
# section (see #converge_overrides).
|
|
1155
1185
|
next unless override.target.is_a?(String) && override.field == :version
|
|
1156
1186
|
|
|
1157
1187
|
name = override.target
|
|
@@ -1266,7 +1296,7 @@ module Bundler
|
|
|
1266
1296
|
def preload_git_source_worker
|
|
1267
1297
|
workers = Bundler.settings.installation_parallelization
|
|
1268
1298
|
|
|
1269
|
-
@preload_git_source_worker ||= Bundler::Worker.new(workers, "Git source preloading", ->(
|
|
1299
|
+
@preload_git_source_worker ||= Bundler::Worker.new(workers, "Git source preloading", ->(sources, _) { sources.each(&:specs) })
|
|
1270
1300
|
end
|
|
1271
1301
|
|
|
1272
1302
|
def preload_git_sources
|
|
@@ -1277,7 +1307,13 @@ module Bundler
|
|
|
1277
1307
|
end
|
|
1278
1308
|
|
|
1279
1309
|
begin
|
|
1280
|
-
|
|
1310
|
+
# Sources from the same repository share one cache directory, and
|
|
1311
|
+
# running git in that directory from two workers at once makes the
|
|
1312
|
+
# fetches collide. Preload sources that share a cache in one job, one
|
|
1313
|
+
# after the other, and run the separate caches in parallel.
|
|
1314
|
+
needed_git_sources.group_by(&:cache_path).each_value do |sources|
|
|
1315
|
+
preload_git_source_worker.enq(sources)
|
|
1316
|
+
end
|
|
1281
1317
|
ensure
|
|
1282
1318
|
preload_git_source_worker.stop
|
|
1283
1319
|
end
|
data/lib/bundler/dsl.rb
CHANGED
|
@@ -202,7 +202,12 @@ module Bundler
|
|
|
202
202
|
validate_override_target!(target)
|
|
203
203
|
source_location = caller_locations(1, 1)&.first
|
|
204
204
|
|
|
205
|
-
|
|
205
|
+
# 4.1.0.beta2 spelled `with:` and `in:` as `to:` and `from:`.
|
|
206
|
+
if operations.key?(:from)
|
|
207
|
+
raise ArgumentError, "`from:` and `to:` of `override` are now `in:` and `with:`; write `override #{target.inspect}, with: #{operations.fetch(:to, "<gem>").inspect}, in: #{operations[:from].inspect}`"
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
if operations.key?(:in) || operations.key?(:with)
|
|
206
211
|
add_dependency_override(target, operations, source_location)
|
|
207
212
|
return
|
|
208
213
|
end
|
|
@@ -292,8 +297,16 @@ module Bundler
|
|
|
292
297
|
|
|
293
298
|
def validate_override_target!(target)
|
|
294
299
|
return if target == :all
|
|
295
|
-
|
|
296
|
-
|
|
300
|
+
raise ArgumentError, "override target must be :all or a gem name string, got #{target.inspect}" unless target.is_a?(String)
|
|
301
|
+
validate_override_gem_name!(target)
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# Override names are recorded in the lockfile's OVERRIDES section, so they
|
|
305
|
+
# must be valid gem names.
|
|
306
|
+
def validate_override_gem_name!(name)
|
|
307
|
+
validate_gem_name!(name)
|
|
308
|
+
return if Gem::Specification::VALID_NAME_PATTERN.match?(name)
|
|
309
|
+
raise GemfileError, "#{name.inspect} is not a valid gem name"
|
|
297
310
|
end
|
|
298
311
|
|
|
299
312
|
def validate_override_field!(field)
|
|
@@ -324,40 +337,40 @@ module Bundler
|
|
|
324
337
|
end
|
|
325
338
|
|
|
326
339
|
def add_dependency_override(target, operations, source_location)
|
|
327
|
-
unless operations.key?(:
|
|
328
|
-
raise ArgumentError, "`override #{target.inspect},
|
|
340
|
+
unless operations.key?(:in)
|
|
341
|
+
raise ArgumentError, "`override #{target.inspect}, with:` requires `in:` naming the gem whose dependency is rewritten"
|
|
329
342
|
end
|
|
330
|
-
unless operations.key?(:
|
|
331
|
-
raise ArgumentError, "`override #{target.inspect},
|
|
343
|
+
unless operations.key?(:with)
|
|
344
|
+
raise ArgumentError, "`override #{target.inspect}, in:` requires `with:`; use `with: nil` to drop the dependency or `with: \"<gem>\"` to replace it"
|
|
332
345
|
end
|
|
333
346
|
|
|
334
|
-
from = operations[:
|
|
335
|
-
|
|
347
|
+
from = operations[:in]
|
|
348
|
+
with = operations[:with]
|
|
336
349
|
requirement = operations[:version]
|
|
337
350
|
|
|
338
|
-
raise ArgumentError, "`override :all` does not accept `
|
|
339
|
-
raise ArgumentError, "`
|
|
340
|
-
raise ArgumentError, "`
|
|
341
|
-
raise ArgumentError, "`
|
|
342
|
-
|
|
343
|
-
|
|
351
|
+
raise ArgumentError, "`override :all` does not accept `in:`" if target == :all
|
|
352
|
+
raise ArgumentError, "`in:` must be a gem name string, got #{from.inspect}" unless from.is_a?(String)
|
|
353
|
+
raise ArgumentError, "`with:` must be a gem name string or nil, got #{with.inspect}" unless with.nil? || with.is_a?(String)
|
|
354
|
+
raise ArgumentError, "`with:` must name a gem other than #{target.inspect} and #{from.inspect}" if with == target || with == from
|
|
355
|
+
validate_override_gem_name!(from)
|
|
356
|
+
validate_override_gem_name!(with) if with
|
|
344
357
|
|
|
345
|
-
unsupported = operations.keys - [:
|
|
358
|
+
unsupported = operations.keys - [:in, :with, :version]
|
|
346
359
|
if unsupported.any?
|
|
347
|
-
raise ArgumentError, "unsupported override field `#{unsupported.first}:` with `
|
|
360
|
+
raise ArgumentError, "unsupported override field `#{unsupported.first}:` with `in:`; supported fields: `with:`, `version:`"
|
|
348
361
|
end
|
|
349
362
|
|
|
350
363
|
if operations.key?(:version)
|
|
351
|
-
raise ArgumentError, "`version:` with `
|
|
352
|
-
raise ArgumentError, "`version:` with `
|
|
364
|
+
raise ArgumentError, "`version:` with `in:` requires `with:` to name a replacement gem" if with.nil?
|
|
365
|
+
raise ArgumentError, "`version:` with `in:` must be a version requirement string, got #{requirement.inspect}" unless requirement.is_a?(String)
|
|
353
366
|
validate_override_operation!(requirement)
|
|
354
367
|
end
|
|
355
368
|
|
|
356
369
|
if @overrides.any? {|o| o.target == target && o.from == from }
|
|
357
|
-
raise ArgumentError, "duplicate override for #{target.inspect} `
|
|
370
|
+
raise ArgumentError, "duplicate override for #{target.inspect} `in: #{from.inspect}`"
|
|
358
371
|
end
|
|
359
372
|
|
|
360
|
-
@overrides << Override.new(target, :
|
|
373
|
+
@overrides << Override.new(target, :with, with, from: from, requirement: requirement, source_location: source_location)
|
|
361
374
|
end
|
|
362
375
|
|
|
363
376
|
# Dropping a gem the Gemfile requires directly would leave it installed
|
|
@@ -66,6 +66,8 @@ module Bundler
|
|
|
66
66
|
end
|
|
67
67
|
fetch(new_uri, headers, counter + 1)
|
|
68
68
|
when Gem::Net::HTTPRequestedRangeNotSatisfiable
|
|
69
|
+
raise bad_response(response) unless headers.key?("Range")
|
|
70
|
+
|
|
69
71
|
new_headers = headers.dup
|
|
70
72
|
new_headers.delete("Range")
|
|
71
73
|
fetch(uri, new_headers)
|
|
@@ -81,9 +83,7 @@ module Bundler
|
|
|
81
83
|
when Gem::Net::HTTPNotFound
|
|
82
84
|
raise FallbackError, "Gem::Net::HTTPNotFound: #{filtered_uri}"
|
|
83
85
|
else
|
|
84
|
-
|
|
85
|
-
message += ": #{response.body}" unless response.body.empty?
|
|
86
|
-
raise HTTPError, message
|
|
86
|
+
raise bad_response(response)
|
|
87
87
|
end
|
|
88
88
|
end
|
|
89
89
|
|
|
@@ -121,6 +121,12 @@ module Bundler
|
|
|
121
121
|
|
|
122
122
|
private
|
|
123
123
|
|
|
124
|
+
def bad_response(response)
|
|
125
|
+
message = "Gem::#{response.class.name.gsub(/\AGem::/, "")}"
|
|
126
|
+
message += ": #{response.body}" unless response.body.empty?
|
|
127
|
+
HTTPError.new(message)
|
|
128
|
+
end
|
|
129
|
+
|
|
124
130
|
def network_down_error(uri, filtered_uri)
|
|
125
131
|
host = uri.host
|
|
126
132
|
host_port = "#{host}:#{uri.port}"
|
data/lib/bundler/fetcher.rb
CHANGED
|
@@ -157,7 +157,10 @@ module Bundler
|
|
|
157
157
|
elsif cached_spec_path = gemspec_cached_path(spec_file_name)
|
|
158
158
|
Bundler.load_gemspec(cached_spec_path)
|
|
159
159
|
else
|
|
160
|
-
|
|
160
|
+
body = Bundler::Retry.new("fetcher", FAIL_ERRORS).attempts do
|
|
161
|
+
downloader.fetch(uri).body
|
|
162
|
+
end
|
|
163
|
+
Bundler.safe_load_marshal Bundler.rubygems.inflate(body)
|
|
161
164
|
end
|
|
162
165
|
raise MarshalError, "is #{spec.inspect}" unless spec.is_a?(Gem::Specification)
|
|
163
166
|
spec
|
|
@@ -19,6 +19,7 @@ module Bundler
|
|
|
19
19
|
add_sources
|
|
20
20
|
add_platforms
|
|
21
21
|
add_dependencies
|
|
22
|
+
add_overrides
|
|
22
23
|
add_content_addresses
|
|
23
24
|
add_checksums
|
|
24
25
|
add_locked_ruby_version
|
|
@@ -67,6 +68,11 @@ module Bundler
|
|
|
67
68
|
end
|
|
68
69
|
end
|
|
69
70
|
|
|
71
|
+
def add_overrides
|
|
72
|
+
overrides = definition.overrides_to_lock
|
|
73
|
+
add_section("OVERRIDES", overrides) unless overrides.empty?
|
|
74
|
+
end
|
|
75
|
+
|
|
70
76
|
def add_content_addresses
|
|
71
77
|
content_addresses = definition.resolve.filter_map do |spec|
|
|
72
78
|
next unless Gem::ContentAddress.content_addressed?(spec, validate_ruby_abi: false)
|
|
@@ -36,12 +36,14 @@ module Bundler
|
|
|
36
36
|
:bundler_version,
|
|
37
37
|
:ruby_version,
|
|
38
38
|
:checksums,
|
|
39
|
+
:overrides,
|
|
39
40
|
)
|
|
40
41
|
|
|
41
42
|
BUNDLED = "BUNDLED WITH"
|
|
42
43
|
DEPENDENCIES = "DEPENDENCIES"
|
|
43
44
|
CHECKSUMS = "CHECKSUMS"
|
|
44
45
|
CONTENT_ADDRESSES = "CONTENT ADDRESSES"
|
|
46
|
+
OVERRIDES = "OVERRIDES"
|
|
45
47
|
PLATFORMS = "PLATFORMS"
|
|
46
48
|
RUBY = "RUBY VERSION"
|
|
47
49
|
GIT = "GIT"
|
|
@@ -61,7 +63,11 @@ module Bundler
|
|
|
61
63
|
Gem::Version.create("4.1.0") => [CONTENT_ADDRESSES].freeze,
|
|
62
64
|
}.freeze
|
|
63
65
|
|
|
64
|
-
|
|
66
|
+
# OVERRIDES is deliberately not in SECTIONS_BY_VERSION_INTRODUCED. Sections
|
|
67
|
+
# listed there are ignored when comparing a lockfile bundled with an older
|
|
68
|
+
# Bundler, so a lockfile still BUNDLED WITH 4.0 would never get its
|
|
69
|
+
# overrides recorded while the resolution stays the same.
|
|
70
|
+
KNOWN_SECTIONS = (SECTIONS_BY_VERSION_INTRODUCED.values.flatten + [OVERRIDES]).freeze
|
|
65
71
|
|
|
66
72
|
ENVIRONMENT_VERSION_SECTIONS = [BUNDLED, RUBY].freeze
|
|
67
73
|
deprecate_constant(:ENVIRONMENT_VERSION_SECTIONS)
|
|
@@ -104,6 +110,7 @@ module Bundler
|
|
|
104
110
|
@dependencies = {}
|
|
105
111
|
@parse_method = nil
|
|
106
112
|
@specs = {}
|
|
113
|
+
@overrides = nil
|
|
107
114
|
@lockfile_path = lockfile_path || begin
|
|
108
115
|
SharedHelpers.relative_lockfile_path
|
|
109
116
|
rescue GemfileNotFound
|
|
@@ -144,6 +151,9 @@ module Bundler
|
|
|
144
151
|
@parse_method = :parse_checksum
|
|
145
152
|
elsif line == CONTENT_ADDRESSES
|
|
146
153
|
@parse_method = :parse_content_address
|
|
154
|
+
elsif line == OVERRIDES
|
|
155
|
+
@overrides = []
|
|
156
|
+
@parse_method = :parse_override
|
|
147
157
|
elsif line == PLATFORMS
|
|
148
158
|
@parse_method = :parse_platform
|
|
149
159
|
elsif line == RUBY
|
|
@@ -270,6 +280,12 @@ module Bundler
|
|
|
270
280
|
@dependencies[dep.name] = dep
|
|
271
281
|
end
|
|
272
282
|
|
|
283
|
+
def parse_override(line)
|
|
284
|
+
raise ArgumentError, "invalid override in lockfile: #{line.inspect}" unless line.start_with?(" ") && line[2] != " "
|
|
285
|
+
|
|
286
|
+
@overrides << Override.from_lock(line[2..])
|
|
287
|
+
end
|
|
288
|
+
|
|
273
289
|
def parse_checksum(line)
|
|
274
290
|
return unless line =~ NAME_VERSION
|
|
275
291
|
|
data/lib/bundler/man/gemfile.5
CHANGED
|
@@ -521,32 +521,41 @@ gem "rails", "~> 7\.0"
|
|
|
521
521
|
.fi
|
|
522
522
|
.IP "" 0
|
|
523
523
|
.P
|
|
524
|
-
The override only affects resolution and the install\-time Ruby/RubyGems compatibility checks; \fBGemfile\.lock\fR
|
|
524
|
+
The override only affects resolution and the install\-time Ruby/RubyGems compatibility checks; the gems in \fBGemfile\.lock\fR continue to reflect the resolved versions, not the rewritten requirements\. The overrides themselves are recorded in the lockfile's \fBOVERRIDES\fR section, one line per field, sorted:
|
|
525
|
+
.IP "" 4
|
|
526
|
+
.nf
|
|
527
|
+
OVERRIDES
|
|
528
|
+
"rails", version: ">= 8\.0"
|
|
529
|
+
:all, required_ruby_version: :ignore_upper
|
|
530
|
+
.fi
|
|
531
|
+
.IP "" 0
|
|
532
|
+
.P
|
|
533
|
+
Requirements are recorded in normalized form, so \fB">=8\.0"\fR and \fB">= 8\.0"\fR are the same override\. A frozen install fails when the Gemfile's overrides differ from the recorded ones\. Adding or removing a \fB:all\fR or metadata override rewrites the section and keeps the locked versions\. The exception is a locked gem that is not installed and whose metadata rejects the current Ruby\. Bundler re\-resolves it, as it does without the override\. Run \fBbundle update\fR to re\-resolve under the override\. When resolution still fails, Bundler appends the active overrides (with their Gemfile location) to the error message so it is clear which override shaped the constraint set\.
|
|
525
534
|
.SS "DROPPING OR REPLACING A DEPENDENCY"
|
|
526
|
-
\
|
|
535
|
+
\fBwith:\fR and \fBin:\fR rewrite a single dependency of a single gem:
|
|
527
536
|
.IP "" 4
|
|
528
537
|
.nf
|
|
529
|
-
override <target>,
|
|
530
|
-
override <target>,
|
|
538
|
+
override <target>, with: nil, in: <gem>
|
|
539
|
+
override <target>, with: <replacement>, in: <gem>, version: <requirement>
|
|
531
540
|
.fi
|
|
532
541
|
.IP "" 0
|
|
533
542
|
.P
|
|
534
|
-
\
|
|
543
|
+
\fBwith: nil\fR removes the dependency of \fB<gem>\fR on \fB<target>\fR, so \fB<target>\fR is not installed unless something else still requires it\. \fBwith: <replacement>\fR makes \fB<gem>\fR depend on \fB<replacement>\fR instead of \fB<target>\fR\. The requirement \fB<gem>\fR put on \fB<target>\fR is discarded, and the optional \fBversion:\fR gives the replacement its own\. Both forms apply whether \fB<gem>\fR is a direct or a transitive dependency\.
|
|
535
544
|
.P
|
|
536
|
-
\
|
|
545
|
+
\fBin:\fR is required, and so is \fBwith:\fR once \fBin:\fR is given\. To rewrite the same dependency of several gems, write one \fBoverride\fR per gem\. It is an error to declare the same \fB<target>\fR and \fBin:\fR twice, to drop a gem that the Gemfile requires directly, or to replace a gem that another gem still requires, since both would then be in the bundle\.
|
|
537
546
|
.IP "" 4
|
|
538
547
|
.nf
|
|
539
548
|
# jekyll only loads em\-websocket for `jekyll serve \-\-livereload`\.
|
|
540
|
-
override "em\-websocket",
|
|
549
|
+
override "em\-websocket", with: nil, in: "jekyll"
|
|
541
550
|
|
|
542
551
|
# Use an API\-compatible gem that provides the same files\.
|
|
543
|
-
override "foo",
|
|
552
|
+
override "foo", with: "foo\-lite", in: "bar"
|
|
544
553
|
.fi
|
|
545
554
|
.IP "" 0
|
|
546
555
|
.P
|
|
547
556
|
Bundler does not check what a gem loads at runtime\. If \fB<gem>\fR requires \fB<target>\fR unconditionally, dropping it makes that require raise \fBLoadError\fR, as with jekyll's dependency on jekyll\-sass\-converter or the adapters that faraday 1\.x requires on load\. A replacement only works when it provides the files \fB<gem>\fR requires, and it does not take over the name of \fB<target>\fR: \fBGem\.loaded_specs\fR has no entry for \fB<target>\fR, and \fBgem "<target>"\fR fails\.
|
|
548
557
|
.P
|
|
549
|
-
\fBGemfile\.lock\fR keeps listing \fB<target>\fR under \fB<gem>\fR as the gem publishes it, while the locked gems leave \fB<target>\fR out or include \fB<replacement>\fR\. A frozen install accepts that lockfile as long as the Gemfile still has the override\. Removing the override makes Bundler resolve \fB<target>\fR again\.
|
|
558
|
+
\fBGemfile\.lock\fR keeps listing \fB<target>\fR under \fB<gem>\fR as the gem publishes it, while the locked gems leave \fB<target>\fR out or include \fB<replacement>\fR, and the \fBOVERRIDES\fR section records the rewrite so tools that read the lockfile can apply it\. A frozen install accepts that lockfile as long as the Gemfile still has the override\. Removing the override makes Bundler resolve \fB<target>\fR again\.
|
|
550
559
|
.SH "SOURCE PRIORITY"
|
|
551
560
|
When attempting to locate a gem to satisfy a gem requirement, bundler uses the following priority order:
|
|
552
561
|
.IP "1." 4
|
|
@@ -623,36 +623,49 @@ Declaring the same `target` and `field` twice is an error.
|
|
|
623
623
|
gem "rails", "~> 7.0"
|
|
624
624
|
|
|
625
625
|
The override only affects resolution and the install-time Ruby/RubyGems
|
|
626
|
-
compatibility checks; `Gemfile.lock`
|
|
627
|
-
versions, not the rewritten requirements.
|
|
626
|
+
compatibility checks; the gems in `Gemfile.lock` continue to reflect the
|
|
627
|
+
resolved versions, not the rewritten requirements. The overrides themselves are
|
|
628
|
+
recorded in the lockfile's `OVERRIDES` section, one line per field, sorted:
|
|
629
|
+
|
|
630
|
+
OVERRIDES
|
|
631
|
+
"rails", version: ">= 8.0"
|
|
632
|
+
:all, required_ruby_version: :ignore_upper
|
|
633
|
+
|
|
634
|
+
Requirements are recorded in normalized form, so `">=8.0"` and `">= 8.0"` are
|
|
635
|
+
the same override. A frozen install fails when the Gemfile's overrides differ
|
|
636
|
+
from the recorded ones. Adding or removing a `:all` or metadata override
|
|
637
|
+
rewrites the section and keeps the locked versions. The exception is a locked
|
|
638
|
+
gem that is not installed and whose metadata rejects the current Ruby. Bundler
|
|
639
|
+
re-resolves it, as it does without the override. Run `bundle update` to
|
|
640
|
+
re-resolve under the override. When resolution still fails,
|
|
628
641
|
Bundler appends the active overrides (with their Gemfile location) to the
|
|
629
642
|
error message so it is clear which override shaped the constraint set.
|
|
630
643
|
|
|
631
644
|
### DROPPING OR REPLACING A DEPENDENCY
|
|
632
645
|
|
|
633
|
-
`
|
|
646
|
+
`with:` and `in:` rewrite a single dependency of a single gem:
|
|
634
647
|
|
|
635
|
-
override <target>,
|
|
636
|
-
override <target>,
|
|
648
|
+
override <target>, with: nil, in: <gem>
|
|
649
|
+
override <target>, with: <replacement>, in: <gem>, version: <requirement>
|
|
637
650
|
|
|
638
|
-
`
|
|
639
|
-
not installed unless something else still requires it. `
|
|
651
|
+
`with: nil` removes the dependency of `<gem>` on `<target>`, so `<target>` is
|
|
652
|
+
not installed unless something else still requires it. `with: <replacement>`
|
|
640
653
|
makes `<gem>` depend on `<replacement>` instead of `<target>`. The requirement
|
|
641
654
|
`<gem>` put on `<target>` is discarded, and the optional `version:` gives the
|
|
642
655
|
replacement its own. Both forms apply whether `<gem>` is a direct or a
|
|
643
656
|
transitive dependency.
|
|
644
657
|
|
|
645
|
-
`
|
|
658
|
+
`in:` is required, and so is `with:` once `in:` is given. To rewrite the
|
|
646
659
|
same dependency of several gems, write one `override` per gem. It is an error
|
|
647
|
-
to declare the same `<target>` and `
|
|
660
|
+
to declare the same `<target>` and `in:` twice, to drop a gem that the
|
|
648
661
|
Gemfile requires directly, or to replace a gem that another gem still
|
|
649
662
|
requires, since both would then be in the bundle.
|
|
650
663
|
|
|
651
664
|
# jekyll only loads em-websocket for `jekyll serve --livereload`.
|
|
652
|
-
override "em-websocket",
|
|
665
|
+
override "em-websocket", with: nil, in: "jekyll"
|
|
653
666
|
|
|
654
667
|
# Use an API-compatible gem that provides the same files.
|
|
655
|
-
override "foo",
|
|
668
|
+
override "foo", with: "foo-lite", in: "bar"
|
|
656
669
|
|
|
657
670
|
Bundler does not check what a gem loads at runtime. If `<gem>` requires
|
|
658
671
|
`<target>` unconditionally, dropping it makes that require raise `LoadError`,
|
|
@@ -662,9 +675,10 @@ files `<gem>` requires, and it does not take over the name of `<target>`:
|
|
|
662
675
|
`Gem.loaded_specs` has no entry for `<target>`, and `gem "<target>"` fails.
|
|
663
676
|
|
|
664
677
|
`Gemfile.lock` keeps listing `<target>` under `<gem>` as the gem publishes it,
|
|
665
|
-
while the locked gems leave `<target>` out or include `<replacement
|
|
666
|
-
|
|
667
|
-
|
|
678
|
+
while the locked gems leave `<target>` out or include `<replacement>`, and the
|
|
679
|
+
`OVERRIDES` section records the rewrite so tools that read the lockfile can
|
|
680
|
+
apply it. A frozen install accepts that lockfile as long as the Gemfile still
|
|
681
|
+
has the override. Removing the override makes Bundler resolve `<target>` again.
|
|
668
682
|
|
|
669
683
|
## SOURCE PRIORITY
|
|
670
684
|
|
|
@@ -27,9 +27,18 @@ module Bundler
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def self.prefer_content_addressable(matching)
|
|
30
|
-
|
|
31
|
-
return matching
|
|
32
|
-
|
|
30
|
+
first = matching.index {|s| Gem::ContentAddress.content_addressed?(s, validate_ruby_abi: false) }
|
|
31
|
+
return matching unless first
|
|
32
|
+
|
|
33
|
+
addressable = [matching[first]]
|
|
34
|
+
non_addressable = matching.take(first)
|
|
35
|
+
matching.drop(first + 1).each do |s|
|
|
36
|
+
if Gem::ContentAddress.content_addressed?(s, validate_ruby_abi: false)
|
|
37
|
+
addressable << s
|
|
38
|
+
else
|
|
39
|
+
non_addressable << s
|
|
40
|
+
end
|
|
41
|
+
end
|
|
33
42
|
compatible = addressable.select(&:matches_current_metadata?)
|
|
34
43
|
return compatible if compatible.any?
|
|
35
44
|
|