rubygems-update 3.2.10 → 3.2.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e482e0b6b43dc7594405f537f149db6f78314c06e2a15c609f4023951ca0d7d7
4
- data.tar.gz: ac6f951b732cdb60f3164e65d2c46f31c8e04c4bf70d50efc0059ad7f4ae2e6d
3
+ metadata.gz: 027ee31fe24ec2094fdc8bcfecae4261c36ce412a813b2d0c68376679de49d26
4
+ data.tar.gz: deb4ea6deab65dc34df00c5836443743ed0ae367fc191dc2050ecc598fc76fc1
5
5
  SHA512:
6
- metadata.gz: db6d0b7178aa13690c92fe513b08c1fb05772866384cf258b2350daa49fe1a635163511306ac2dc3b392a77a751404925478e4cabb61901c1ca46052a993b0cc
7
- data.tar.gz: b545dc793092b3d0b79318763ca84e8cb0e8a91288de8351592cc11b9164930a22320701f0a8ad36051e0b986b65df6b5a400fcf6838e03f31f4e215cf431514
6
+ metadata.gz: 0f876e2acbd22963c1a5cd0e799bd34c801c6751293030c715d1eb4d0faddc010fe6c9b353e9d0ce1540f601773b4e295d3b16ee3d597dcbe36867509f977e5d
7
+ data.tar.gz: 21e3b99cc9733a4ce41e0aac1c5f97dac2053b87f58388dfabf8658c5bdd506484c4576e96137fa968f89aea368a81ff4f4ca9e5a141b6de72e4cadbc7129efb
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # 3.2.11 / 2021-02-17
2
+
3
+ ## Enhancements:
4
+
5
+ * Optionally fallback to IPv4 when IPv6 is unreachable. Pull request #2662
6
+ by sonalkr132
7
+
1
8
  # 3.2.10 / 2021-02-15
2
9
 
3
10
  ## Documentation:
data/Manifest.txt CHANGED
@@ -354,6 +354,7 @@ lib/rubygems/config_file.rb
354
354
  lib/rubygems/core_ext/kernel_gem.rb
355
355
  lib/rubygems/core_ext/kernel_require.rb
356
356
  lib/rubygems/core_ext/kernel_warn.rb
357
+ lib/rubygems/core_ext/tcpsocket_init.rb
357
358
  lib/rubygems/defaults.rb
358
359
  lib/rubygems/dependency.rb
359
360
  lib/rubygems/dependency_installer.rb
data/bundler/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # 2.2.11 (February 17, 2021)
2
+
3
+ ## Bug fixes:
4
+
5
+ - Revert disable_multisource changes [#4385](https://github.com/rubygems/rubygems/pull/4385)
6
+
1
7
  # 2.2.10 (February 15, 2021)
2
8
 
3
9
  ## Security fixes:
@@ -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 = "2021-02-15".freeze
8
- @git_commit_sha = "cc7c333721".freeze
7
+ @built_at = "2021-02-17".freeze
8
+ @git_commit_sha = "6ca677a0eb".freeze
9
9
  @release = true
10
10
  # end ivars
11
11
 
@@ -106,19 +106,6 @@ module Bundler
106
106
  @locked_platforms = []
107
107
  end
108
108
 
109
- @locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
110
- @disable_multisource = !Bundler.frozen_bundle? || @locked_gem_sources.none? {|s| s.remotes.size > 1 }
111
-
112
- unless @disable_multisource
113
- msg = "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. " \
114
- "You should regenerate your lockfile in a non frozen environment."
115
-
116
- Bundler::SharedHelpers.major_deprecation 2, msg
117
-
118
- @sources.allow_multisource!
119
- @locked_gem_sources.each(&:allow_multisource!)
120
- end
121
-
122
109
  @unlock[:gems] ||= []
123
110
  @unlock[:sources] ||= []
124
111
  @unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
@@ -158,14 +145,6 @@ module Bundler
158
145
  end
159
146
  end
160
147
 
161
- def disable_multisource?
162
- @disable_multisource
163
- end
164
-
165
- def allow_multisource!
166
- @disable_multisource = false
167
- end
168
-
169
148
  def resolve_with_cache!
170
149
  raise "Specs already loaded" if @specs
171
150
  sources.cached!
@@ -285,7 +264,7 @@ module Bundler
285
264
  # Run a resolve against the locally available gems
286
265
  Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
287
266
  expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote)
288
- Resolver.resolve(expanded_dependencies, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
267
+ Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
289
268
  end
290
269
  end
291
270
  end
@@ -551,9 +530,6 @@ module Bundler
551
530
  attr_reader :sources
552
531
  private :sources
553
532
 
554
- attr_reader :locked_gem_sources
555
- private :locked_gem_sources
556
-
557
533
  def nothing_changed?
558
534
  !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform
559
535
  end
@@ -678,20 +654,21 @@ module Bundler
678
654
  end
679
655
 
680
656
  def converge_rubygems_sources
681
- return false if disable_multisource?
657
+ return false if Bundler.feature_flag.disable_multisource?
682
658
 
683
- return false if locked_gem_sources.empty?
659
+ changes = false
684
660
 
661
+ # Get the RubyGems sources from the Gemfile.lock
662
+ locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
685
663
  # Get the RubyGems remotes from the Gemfile
686
664
  actual_remotes = sources.rubygems_remotes
687
- return false if actual_remotes.empty?
688
-
689
- changes = false
690
665
 
691
666
  # If there is a RubyGems source in both
692
- locked_gem_sources.each do |locked_gem|
693
- # Merge the remotes from the Gemfile into the Gemfile.lock
694
- changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
667
+ if !locked_gem_sources.empty? && !actual_remotes.empty?
668
+ locked_gem_sources.each do |locked_gem|
669
+ # Merge the remotes from the Gemfile into the Gemfile.lock
670
+ changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
671
+ end
695
672
  end
696
673
 
697
674
  changes
@@ -916,18 +893,30 @@ module Bundler
916
893
  # Record the specs available in each gem's source, so that those
917
894
  # specs will be available later when the resolver knows where to
918
895
  # look for that gemspec (or its dependencies)
919
- source_requirements = { :default => sources.default_source }.merge(dependency_source_requirements)
896
+ default = sources.default_source
897
+ source_requirements = { :default => default }
898
+ default = nil unless Bundler.feature_flag.disable_multisource?
899
+ dependencies.each do |dep|
900
+ next unless source = dep.source || default
901
+ source_requirements[dep.name] = source
902
+ end
920
903
  metadata_dependencies.each do |dep|
921
904
  source_requirements[dep.name] = sources.metadata_source
922
905
  end
923
- source_requirements[:global] = index unless disable_multisource?
924
906
  source_requirements[:default_bundler] = source_requirements["bundler"] || source_requirements[:default]
925
907
  source_requirements["bundler"] = sources.metadata_source # needs to come last to override
926
908
  source_requirements
927
909
  end
928
910
 
929
911
  def pinned_spec_names(skip = nil)
930
- dependency_source_requirements.reject {|_, source| source == skip }.keys
912
+ pinned_names = []
913
+ default = Bundler.feature_flag.disable_multisource? && sources.default_source
914
+ @dependencies.each do |dep|
915
+ next unless dep_source = dep.source || default
916
+ next if dep_source == skip
917
+ pinned_names << dep.name
918
+ end
919
+ pinned_names
931
920
  end
932
921
 
933
922
  def requested_groups
@@ -984,18 +973,5 @@ module Bundler
984
973
 
985
974
  Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes)
986
975
  end
987
-
988
- def dependency_source_requirements
989
- @dependency_source_requirements ||= begin
990
- source_requirements = {}
991
- default = disable_multisource? && sources.default_source
992
- dependencies.each do |dep|
993
- dep_source = dep.source || default
994
- next unless dep_source
995
- source_requirements[dep.name] = dep_source
996
- end
997
- source_requirements
998
- end
999
- end
1000
976
  end
1001
977
  end
@@ -24,9 +24,6 @@ module Bundler
24
24
  def initialize
25
25
  @source = nil
26
26
  @sources = SourceList.new
27
-
28
- @global_rubygems_sources = []
29
-
30
27
  @git_sources = {}
31
28
  @dependencies = []
32
29
  @groups = []
@@ -48,7 +45,6 @@ module Bundler
48
45
  @gemfiles << expanded_gemfile_path
49
46
  contents ||= Bundler.read_file(@gemfile.to_s)
50
47
  instance_eval(contents.dup.tap{|x| x.untaint if RUBY_VERSION < "2.7" }, gemfile.to_s, 1)
51
- check_primary_source_safety
52
48
  rescue Exception => e # rubocop:disable Lint/RescueException
53
49
  message = "There was an error " \
54
50
  "#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \
@@ -168,7 +164,8 @@ module Bundler
168
164
  elsif block_given?
169
165
  with_source(@sources.add_rubygems_source("remotes" => source), &blk)
170
166
  else
171
- @global_rubygems_sources << source
167
+ check_primary_source_safety(@sources)
168
+ @sources.global_rubygems_source = source
172
169
  end
173
170
  end
174
171
 
@@ -186,14 +183,24 @@ module Bundler
186
183
  end
187
184
 
188
185
  def path(path, options = {}, &blk)
186
+ unless block_given?
187
+ msg = "You can no longer specify a path source by itself. Instead, \n" \
188
+ "either use the :path option on a gem, or specify the gems that \n" \
189
+ "bundler should find in the path source by passing a block to \n" \
190
+ "the path method, like: \n\n" \
191
+ " path 'dir/containing/rails' do\n" \
192
+ " gem 'rails'\n" \
193
+ " end\n\n"
194
+
195
+ raise DeprecatedError, msg if Bundler.feature_flag.disable_multisource?
196
+ SharedHelpers.major_deprecation(2, msg.strip)
197
+ end
198
+
189
199
  source_options = normalize_hash(options).merge(
190
200
  "path" => Pathname.new(path),
191
201
  "root_path" => gemfile_root,
192
202
  "gemspec" => gemspecs.find {|g| g.name == options["name"] }
193
203
  )
194
-
195
- source_options["global"] = true unless block_given?
196
-
197
204
  source = @sources.add_path_source(source_options)
198
205
  with_source(source, &blk)
199
206
  end
@@ -272,11 +279,6 @@ module Bundler
272
279
  raise GemfileError, "Undefined local variable or method `#{name}' for Gemfile"
273
280
  end
274
281
 
275
- def check_primary_source_safety
276
- check_path_source_safety
277
- check_rubygems_source_safety
278
- end
279
-
280
282
  private
281
283
 
282
284
  def add_git_sources
@@ -438,40 +440,25 @@ repo_name ||= user_name
438
440
  end
439
441
  end
440
442
 
441
- def check_path_source_safety
442
- return if @sources.global_path_source.nil?
443
-
444
- msg = "You can no longer specify a path source by itself. Instead, \n" \
445
- "either use the :path option on a gem, or specify the gems that \n" \
446
- "bundler should find in the path source by passing a block to \n" \
447
- "the path method, like: \n\n" \
448
- " path 'dir/containing/rails' do\n" \
449
- " gem 'rails'\n" \
450
- " end\n\n"
443
+ def check_primary_source_safety(source_list)
444
+ return if source_list.rubygems_primary_remotes.empty? && source_list.global_rubygems_source.nil?
451
445
 
452
- SharedHelpers.major_deprecation(2, msg.strip)
453
- end
454
-
455
- def check_rubygems_source_safety
456
- if @global_rubygems_sources.size <= 1
457
- @sources.global_rubygems_source = @global_rubygems_sources.first
458
- return
459
- end
460
-
461
- @global_rubygems_sources.each do |source|
462
- @sources.add_rubygems_remote(source)
463
- end
464
-
465
- if Bundler.feature_flag.bundler_3_mode?
446
+ if Bundler.feature_flag.disable_multisource?
466
447
  msg = "This Gemfile contains multiple primary sources. " \
467
448
  "Each source after the first must include a block to indicate which gems " \
468
449
  "should come from that source"
450
+ unless Bundler.feature_flag.bundler_2_mode?
451
+ msg += ". To downgrade this error to a warning, run " \
452
+ "`bundle config unset disable_multisource`"
453
+ end
469
454
  raise GemfileEvalError, msg
470
455
  else
471
456
  Bundler::SharedHelpers.major_deprecation 2, "Your Gemfile contains multiple primary sources. " \
472
457
  "Using `source` more than once without a block is a security risk, and " \
473
458
  "may result in installing unexpected gems. To resolve this warning, use " \
474
- "a block to indicate which gems should come from the secondary source."
459
+ "a block to indicate which gems should come from the secondary source. " \
460
+ "To upgrade this warning to an error, run `bundle config set --local " \
461
+ "disable_multisource true`."
475
462
  end
476
463
  end
477
464
 
@@ -32,6 +32,7 @@ module Bundler
32
32
  settings_flag(:cache_all) { bundler_3_mode? }
33
33
  settings_flag(:default_install_uses_path) { bundler_3_mode? }
34
34
  settings_flag(:deployment_means_frozen) { bundler_3_mode? }
35
+ settings_flag(:disable_multisource) { bundler_3_mode? }
35
36
  settings_flag(:forget_cli_options) { bundler_3_mode? }
36
37
  settings_flag(:global_gem_cache) { bundler_3_mode? }
37
38
  settings_flag(:only_update_to_newer_versions) { bundler_3_mode? }
@@ -50,7 +50,6 @@ def gemfile(install = false, options = {}, &gemfile)
50
50
  Bundler::Plugin.gemfile_install(&gemfile) if Bundler.feature_flag.plugins?
51
51
  builder = Bundler::Dsl.new
52
52
  builder.instance_eval(&gemfile)
53
- builder.check_primary_source_safety
54
53
 
55
54
  Bundler.settings.temporary(:frozen => false) do
56
55
  definition = builder.to_definition(nil, true)
@@ -64,6 +64,8 @@ module Bundler
64
64
  @state = nil
65
65
  @specs = {}
66
66
 
67
+ @rubygems_aggregate = Source::Rubygems.new
68
+
67
69
  if lockfile.match(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/)
68
70
  raise LockfileError, "Your #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} contains merge conflicts.\n" \
69
71
  "Run `git checkout HEAD -- #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}` first to get a clean lock."
@@ -87,6 +89,7 @@ module Bundler
87
89
  send("parse_#{@state}", line)
88
90
  end
89
91
  end
92
+ @sources << @rubygems_aggregate unless Bundler.feature_flag.disable_multisource?
90
93
  @specs = @specs.values.sort_by(&:identifier)
91
94
  warn_for_outdated_bundler_version
92
95
  rescue ArgumentError => e
@@ -131,19 +134,16 @@ module Bundler
131
134
  @sources << @current_source
132
135
  end
133
136
  when GEM
134
- source_remotes = Array(@opts["remote"])
135
-
136
- if source_remotes.size == 1
137
+ if Bundler.feature_flag.disable_multisource?
137
138
  @opts["remotes"] = @opts.delete("remote")
138
139
  @current_source = TYPES[@type].from_lock(@opts)
140
+ @sources << @current_source
139
141
  else
140
- source_remotes.each do |url|
141
- rubygems_aggregate.add_remote(url)
142
+ Array(@opts["remote"]).each do |url|
143
+ @rubygems_aggregate.add_remote(url)
142
144
  end
143
- @current_source = rubygems_aggregate
145
+ @current_source = @rubygems_aggregate
144
146
  end
145
-
146
- @sources << @current_source
147
147
  when PLUGIN
148
148
  @current_source = Plugin.source_from_lock(@opts)
149
149
  @sources << @current_source
@@ -245,9 +245,5 @@ module Bundler
245
245
  def parse_ruby(line)
246
246
  @ruby_version = line.strip
247
247
  end
248
-
249
- def rubygems_aggregate
250
- @rubygems_aggregate ||= Source::Rubygems.new
251
- end
252
248
  end
253
249
  end
@@ -56,6 +56,9 @@ Executing \fBbundle config unset \-\-local <name> <value>\fR will delete the con
56
56
  .P
57
57
  Executing bundle with the \fBBUNDLE_IGNORE_CONFIG\fR environment variable set will cause it to ignore all configuration\.
58
58
  .
59
+ .P
60
+ Executing \fBbundle config set \-\-local disable_multisource true\fR upgrades the warning about the Gemfile containing multiple primary sources to an error\. Executing \fBbundle config unset disable_multisource\fR downgrades this error to a warning\.
61
+ .
59
62
  .SH "REMEMBERING OPTIONS"
60
63
  Flags passed to \fBbundle install\fR or the Bundler runtime, such as \fB\-\-path foo\fR or \fB\-\-without production\fR, are remembered between commands and saved to your local application\'s configuration (normally, \fB\./\.bundle/config\fR)\.
61
64
  .
@@ -181,6 +184,9 @@ The following is a list of all configuration keys and their purpose\. You can le
181
184
  \fBdisable_local_revision_check\fR (\fBBUNDLE_DISABLE_LOCAL_REVISION_CHECK\fR): Allow Bundler to use a local git override without checking if the revision present in the lockfile is present in the repository\.
182
185
  .
183
186
  .IP "\(bu" 4
187
+ \fBdisable_multisource\fR (\fBBUNDLE_DISABLE_MULTISOURCE\fR): When set, Gemfiles containing multiple sources will produce errors instead of warnings\. Use \fBbundle config unset disable_multisource\fR to unset\.
188
+ .
189
+ .IP "\(bu" 4
184
190
  \fBdisable_shared_gems\fR (\fBBUNDLE_DISABLE_SHARED_GEMS\fR): Stop Bundler from accessing gems installed to RubyGems\' normal location\.
185
191
  .
186
192
  .IP "\(bu" 4
@@ -47,6 +47,10 @@ configuration only from the local application.
47
47
  Executing bundle with the `BUNDLE_IGNORE_CONFIG` environment variable set will
48
48
  cause it to ignore all configuration.
49
49
 
50
+ Executing `bundle config set --local disable_multisource true` upgrades the warning about
51
+ the Gemfile containing multiple primary sources to an error. Executing `bundle
52
+ config unset disable_multisource` downgrades this error to a warning.
53
+
50
54
  ## REMEMBERING OPTIONS
51
55
 
52
56
  Flags passed to `bundle install` or the Bundler runtime, such as `--path foo` or
@@ -174,6 +178,10 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
174
178
  * `disable_local_revision_check` (`BUNDLE_DISABLE_LOCAL_REVISION_CHECK`):
175
179
  Allow Bundler to use a local git override without checking if the revision
176
180
  present in the lockfile is present in the repository.
181
+ * `disable_multisource` (`BUNDLE_DISABLE_MULTISOURCE`):
182
+ When set, Gemfiles containing multiple sources will produce errors
183
+ instead of warnings.
184
+ Use `bundle config unset disable_multisource` to unset.
177
185
  * `disable_shared_gems` (`BUNDLE_DISABLE_SHARED_GEMS`):
178
186
  Stop Bundler from accessing gems installed to RubyGems' normal location.
179
187
  * `disable_version_check` (`BUNDLE_DISABLE_VERSION_CHECK`):
@@ -105,7 +105,6 @@ module Bundler
105
105
  else
106
106
  builder.eval_gemfile(gemfile)
107
107
  end
108
- builder.check_primary_source_safety
109
108
  definition = builder.to_definition(nil, true)
110
109
 
111
110
  return if definition.dependencies.empty?
@@ -16,13 +16,15 @@ module Bundler
16
16
 
17
17
  version = options[:version] || [">= 0"]
18
18
 
19
- if options[:git]
20
- install_git(names, version, options)
21
- elsif options[:local_git]
22
- install_local_git(names, version, options)
23
- else
24
- sources = options[:source] || Bundler.rubygems.sources
25
- install_rubygems(names, version, sources)
19
+ Bundler.settings.temporary(:disable_multisource => false) do
20
+ if options[:git]
21
+ install_git(names, version, options)
22
+ elsif options[:local_git]
23
+ install_local_git(names, version, options)
24
+ else
25
+ sources = options[:source] || Bundler.rubygems.sources
26
+ install_rubygems(names, version, sources)
27
+ end
26
28
  end
27
29
  end
28
30
 
@@ -82,7 +84,6 @@ module Bundler
82
84
  deps = names.map {|name| Dependency.new name, version }
83
85
 
84
86
  definition = Definition.new(nil, deps, source_list, true)
85
- definition.allow_multisource!
86
87
  install_definition(definition)
87
88
  end
88
89
 
@@ -17,14 +17,15 @@ module Bundler
17
17
  # ==== Returns
18
18
  # <GemBundle>,nil:: If the list of dependencies can be resolved, a
19
19
  # collection of gemspecs is returned. Otherwise, nil is returned.
20
- def self.resolve(requirements, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil)
20
+ def self.resolve(requirements, index, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil)
21
21
  base = SpecSet.new(base) unless base.is_a?(SpecSet)
22
- resolver = new(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
22
+ resolver = new(index, source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
23
23
  result = resolver.start(requirements)
24
24
  SpecSet.new(result)
25
25
  end
26
26
 
27
- def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
27
+ def initialize(index, source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
28
+ @index = index
28
29
  @source_requirements = source_requirements
29
30
  @base = base
30
31
  @resolver = Molinillo::Resolver.new(self, self)
@@ -39,7 +40,7 @@ module Bundler
39
40
  @resolving_only_for_ruby = platforms == [Gem::Platform::RUBY]
40
41
  @gem_version_promoter = gem_version_promoter
41
42
  @use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major?
42
- @no_aggregate_global_source = @source_requirements[:global].nil?
43
+ @lockfile_uses_separate_rubygems_sources = Bundler.feature_flag.disable_multisource?
43
44
 
44
45
  @variant_specific_names = []
45
46
  @generic_names = ["Ruby\0", "RubyGems\0"]
@@ -124,7 +125,8 @@ module Bundler
124
125
  dependency = dependency_proxy.dep
125
126
  name = dependency.name
126
127
  search_result = @search_for[dependency_proxy] ||= begin
127
- results = results_for(dependency, @base[name])
128
+ index = index_for(dependency)
129
+ results = index.search(dependency, @base[name])
128
130
 
129
131
  if vertex = @base_dg.vertex_named(name)
130
132
  locked_requirement = vertex.payload.requirement
@@ -193,26 +195,23 @@ module Bundler
193
195
  search_result
194
196
  end
195
197
 
196
- def index_for(dependency, base)
198
+ def index_for(dependency)
197
199
  source = @source_requirements[dependency.name]
198
200
  if source
199
201
  source.specs
200
- elsif @no_aggregate_global_source
201
- dependency.all_sources.find(-> { Index.new }) do |s|
202
- idx = s.specs
203
- results = idx.search(dependency, base)
204
- next if results.empty? || results == base
205
- return idx
202
+ elsif @lockfile_uses_separate_rubygems_sources
203
+ Index.build do |idx|
204
+ if dependency.all_sources
205
+ dependency.all_sources.each {|s| idx.add_source(s.specs) if s }
206
+ else
207
+ idx.add_source @source_requirements[:default].specs
208
+ end
206
209
  end
207
210
  else
208
- @source_requirements[:global]
211
+ @index
209
212
  end
210
213
  end
211
214
 
212
- def results_for(dependency, base)
213
- index_for(dependency, base).search(dependency, base)
214
- end
215
-
216
215
  def name_for(dependency)
217
216
  dependency.name
218
217
  end
@@ -239,13 +238,11 @@ module Bundler
239
238
 
240
239
  def relevant_sources_for_vertex(vertex)
241
240
  if vertex.root?
242
- [@source_requirements[vertex.name]].compact
243
- elsif @no_aggregate_global_source
241
+ [@source_requirements[vertex.name]]
242
+ elsif @lockfile_uses_separate_rubygems_sources
244
243
  vertex.recursive_predecessors.map do |v|
245
244
  @source_requirements[v.name]
246
- end.compact << @source_requirements[:default]
247
- else
248
- []
245
+ end << @source_requirements[:default]
249
246
  end
250
247
  end
251
248
 
@@ -286,7 +283,7 @@ module Bundler
286
283
  if (base = @base[dependency.name]) && !base.empty?
287
284
  dependency.requirement.satisfied_by?(base.first.version) ? 0 : 1
288
285
  else
289
- all = index_for(dependency, base).search(dependency.name).size
286
+ all = index_for(dependency).search(dependency.name).size
290
287
 
291
288
  if all <= 1
292
289
  all - 1_000_000
@@ -329,7 +326,7 @@ module Bundler
329
326
  "The source does not contain any versions of '#{name}'"
330
327
  end
331
328
  else
332
- message = "Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in any of the gem sources " \
329
+ message = "Could not find gem '#{requirement}' in any of the gem sources " \
333
330
  "listed in your Gemfile#{cache_message}."
334
331
  end
335
332
  raise GemNotFound, message
@@ -414,8 +411,14 @@ module Bundler
414
411
 
415
412
  relevant_sources = if conflict.requirement.source
416
413
  [conflict.requirement.source]
417
- else
414
+ elsif conflict.requirement.all_sources
418
415
  conflict.requirement.all_sources
416
+ elsif @lockfile_uses_separate_rubygems_sources
417
+ # every conflict should have an explicit group of sources when we
418
+ # enforce strict pinning
419
+ raise "no source set for #{conflict}"
420
+ else
421
+ []
419
422
  end.compact.map(&:to_s).uniq.sort
420
423
 
421
424
  metadata_requirement = name.end_with?("\0")
@@ -452,8 +455,7 @@ module Bundler
452
455
  def validate_resolved_specs!(resolved_specs)
453
456
  resolved_specs.each do |v|
454
457
  name = v.name
455
- sources = relevant_sources_for_vertex(v)
456
- next unless sources.any?
458
+ next unless sources = relevant_sources_for_vertex(v)
457
459
  sources.compact!
458
460
  if default_index = sources.index(@source_requirements[:default])
459
461
  sources.delete_at(default_index)
@@ -462,12 +464,14 @@ module Bundler
462
464
  sources.uniq!
463
465
  next if sources.size <= 1
464
466
 
467
+ multisource_disabled = Bundler.feature_flag.disable_multisource?
468
+
465
469
  msg = ["The gem '#{name}' was found in multiple relevant sources."]
466
470
  msg.concat sources.map {|s| " * #{s}" }.sort
467
- msg << "You #{@no_aggregate_global_source ? :must : :should} add this gem to the source block for the source you wish it to be installed from."
471
+ msg << "You #{multisource_disabled ? :must : :should} add this gem to the source block for the source you wish it to be installed from."
468
472
  msg = msg.join("\n")
469
473
 
470
- raise SecurityError, msg if @no_aggregate_global_source
474
+ raise SecurityError, msg if multisource_disabled
471
475
  Bundler.ui.warn "Warning: #{msg}"
472
476
  end
473
477
  end
@@ -20,6 +20,7 @@ module Bundler
20
20
  disable_exec_load
21
21
  disable_local_branch_check
22
22
  disable_local_revision_check
23
+ disable_multisource
23
24
  disable_shared_gems
24
25
  disable_version_check
25
26
  force_ruby_platform
@@ -21,7 +21,6 @@ module Bundler
21
21
  @allow_remote = false
22
22
  @allow_cached = false
23
23
  @caches = [cache_path, *Bundler.rubygems.gem_cache]
24
- @disable_multisource = true
25
24
 
26
25
  Array(options["remotes"] || []).reverse_each {|r| add_remote(r) }
27
26
  end
@@ -50,16 +49,8 @@ module Bundler
50
49
  o.is_a?(Rubygems) && (o.credless_remotes - credless_remotes).empty?
51
50
  end
52
51
 
53
- def disable_multisource?
54
- @disable_multisource
55
- end
56
-
57
- def allow_multisource!
58
- @disable_multisource = false
59
- end
60
-
61
52
  def can_lock?(spec)
62
- return super if disable_multisource?
53
+ return super if Bundler.feature_flag.disable_multisource?
63
54
  spec.source.is_a?(Rubygems)
64
55
  end
65
56
 
@@ -5,41 +5,24 @@ module Bundler
5
5
  attr_reader :path_sources,
6
6
  :git_sources,
7
7
  :plugin_sources,
8
- :global_path_source,
9
- :metadata_source,
10
- :disable_multisource
11
-
12
- def global_rubygems_source
13
- @global_rubygems_source ||= rubygems_aggregate_class.new
14
- end
8
+ :global_rubygems_source,
9
+ :metadata_source
15
10
 
16
11
  def initialize
17
12
  @path_sources = []
18
13
  @git_sources = []
19
14
  @plugin_sources = []
20
15
  @global_rubygems_source = nil
21
- @global_path_source = nil
16
+ @rubygems_aggregate = rubygems_aggregate_class.new
22
17
  @rubygems_sources = []
23
18
  @metadata_source = Source::Metadata.new
24
- @disable_multisource = true
25
- end
26
-
27
- def disable_multisource?
28
- @disable_multisource
29
- end
30
-
31
- def allow_multisource!
32
- rubygems_sources.map(&:allow_multisource!)
33
- @disable_multisource = false
34
19
  end
35
20
 
36
21
  def add_path_source(options = {})
37
22
  if options["gemspec"]
38
23
  add_source_to_list Source::Gemspec.new(options), path_sources
39
24
  else
40
- path_source = add_source_to_list Source::Path.new(options), path_sources
41
- @global_path_source ||= path_source if options["global"]
42
- path_source
25
+ add_source_to_list Source::Path.new(options), path_sources
43
26
  end
44
27
  end
45
28
 
@@ -58,20 +41,24 @@ module Bundler
58
41
  end
59
42
 
60
43
  def global_rubygems_source=(uri)
61
- @global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri)
44
+ if Bundler.feature_flag.disable_multisource?
45
+ @global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri)
46
+ end
47
+ add_rubygems_remote(uri)
62
48
  end
63
49
 
64
50
  def add_rubygems_remote(uri)
65
- global_rubygems_source.add_remote(uri)
66
- global_rubygems_source
51
+ return if Bundler.feature_flag.disable_multisource?
52
+ @rubygems_aggregate.add_remote(uri)
53
+ @rubygems_aggregate
67
54
  end
68
55
 
69
56
  def default_source
70
- global_path_source || global_rubygems_source
57
+ global_rubygems_source || @rubygems_aggregate
71
58
  end
72
59
 
73
60
  def rubygems_sources
74
- @rubygems_sources + [global_rubygems_source]
61
+ @rubygems_sources + [default_source]
75
62
  end
76
63
 
77
64
  def rubygems_remotes
@@ -88,7 +75,7 @@ module Bundler
88
75
 
89
76
  def lock_sources
90
77
  lock_sources = (path_sources + git_sources + plugin_sources).sort_by(&:to_s)
91
- if disable_multisource?
78
+ if Bundler.feature_flag.disable_multisource?
92
79
  lock_sources + rubygems_sources.sort_by(&:to_s)
93
80
  else
94
81
  lock_sources << combine_rubygems_sources
@@ -105,9 +92,9 @@ module Bundler
105
92
  end
106
93
  end
107
94
 
108
- replacement_rubygems = !disable_multisource? &&
95
+ replacement_rubygems = !Bundler.feature_flag.disable_multisource? &&
109
96
  replacement_sources.detect {|s| s.is_a?(Source::Rubygems) }
110
- @global_rubygems_source = replacement_rubygems if replacement_rubygems
97
+ @rubygems_aggregate = replacement_rubygems if replacement_rubygems
111
98
 
112
99
  return true if !equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources)
113
100
  return true if replacement_rubygems && rubygems_remotes.sort_by(&:to_s) != replacement_rubygems.remotes.sort_by(&:to_s)
@@ -123,6 +110,10 @@ module Bundler
123
110
  all_sources.each(&:remote!)
124
111
  end
125
112
 
113
+ def rubygems_primary_remotes
114
+ @rubygems_aggregate.remotes
115
+ end
116
+
126
117
  private
127
118
 
128
119
  def rubygems_aggregate_class
@@ -145,9 +136,7 @@ module Bundler
145
136
  end
146
137
 
147
138
  def combine_rubygems_sources
148
- aggregate_source = Source::Rubygems.new("remotes" => rubygems_remotes)
149
- aggregate_source.allow_multisource! unless disable_multisource?
150
- aggregate_source
139
+ Source::Rubygems.new("remotes" => rubygems_remotes)
151
140
  end
152
141
 
153
142
  def warn_on_git_protocol(source)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  module Bundler
4
- VERSION = "2.2.10".freeze
4
+ VERSION = "2.2.11".freeze
5
5
 
6
6
  def self.bundler_major_version
7
7
  @bundler_major_version ||= VERSION.split(".").first.to_i
data/lib/rubygems.rb CHANGED
@@ -8,7 +8,7 @@
8
8
  require 'rbconfig'
9
9
 
10
10
  module Gem
11
- VERSION = "3.2.10".freeze
11
+ VERSION = "3.2.11".freeze
12
12
  end
13
13
 
14
14
  # Must be first since it unloads the prelude from 1.9.2
@@ -45,6 +45,7 @@ class Gem::ConfigFile
45
45
  DEFAULT_UPDATE_SOURCES = true
46
46
  DEFAULT_CONCURRENT_DOWNLOADS = 8
47
47
  DEFAULT_CERT_EXPIRATION_LENGTH_DAYS = 365
48
+ DEFAULT_IPV4_FALLBACK_ENABLED = false
48
49
 
49
50
  ##
50
51
  # For Ruby packagers to set configuration defaults. Set in
@@ -140,6 +141,12 @@ class Gem::ConfigFile
140
141
 
141
142
  attr_accessor :cert_expiration_length_days
142
143
 
144
+ ##
145
+ # == Experimental ==
146
+ # Fallback to IPv4 when IPv6 is not reachable or slow (default: false)
147
+
148
+ attr_accessor :ipv4_fallback_enabled
149
+
143
150
  ##
144
151
  # Path name of directory or file of openssl client certificate, used for remote https connection with client authentication
145
152
 
@@ -175,6 +182,7 @@ class Gem::ConfigFile
175
182
  @update_sources = DEFAULT_UPDATE_SOURCES
176
183
  @concurrent_downloads = DEFAULT_CONCURRENT_DOWNLOADS
177
184
  @cert_expiration_length_days = DEFAULT_CERT_EXPIRATION_LENGTH_DAYS
185
+ @ipv4_fallback_enabled = ENV['IPV4_FALLBACK_ENABLED'] == 'true' || DEFAULT_IPV4_FALLBACK_ENABLED
178
186
 
179
187
  operating_system_config = Marshal.load Marshal.dump(OPERATING_SYSTEM_DEFAULTS)
180
188
  platform_config = Marshal.load Marshal.dump(PLATFORM_DEFAULTS)
@@ -203,6 +211,7 @@ class Gem::ConfigFile
203
211
  @disable_default_gem_server = @hash[:disable_default_gem_server] if @hash.key? :disable_default_gem_server
204
212
  @sources = @hash[:sources] if @hash.key? :sources
205
213
  @cert_expiration_length_days = @hash[:cert_expiration_length_days] if @hash.key? :cert_expiration_length_days
214
+ @ipv4_fallback_enabled = @hash[:ipv4_fallback_enabled] if @hash.key? :ipv4_fallback_enabled
206
215
 
207
216
  @ssl_verify_mode = @hash[:ssl_verify_mode] if @hash.key? :ssl_verify_mode
208
217
  @ssl_ca_cert = @hash[:ssl_ca_cert] if @hash.key? :ssl_ca_cert
@@ -0,0 +1,49 @@
1
+ require 'socket'
2
+
3
+ module CoreExtensions
4
+ module TCPSocketExt
5
+ def self.prepended(base)
6
+ base.prepend Initializer
7
+ end
8
+
9
+ module Initializer
10
+ CONNECTION_TIMEOUT = 5
11
+ IPV4_DELAY_SECONDS = 0.1
12
+
13
+ def initialize(host, serv, *rest)
14
+ mutex = Mutex.new
15
+ addrs = []
16
+ cond_var = ConditionVariable.new
17
+
18
+ Addrinfo.foreach(host, serv, nil, :STREAM) do |addr|
19
+ Thread.report_on_exception = false if defined? Thread.report_on_exception = ()
20
+
21
+ Thread.new(addr) do
22
+ # give head start to ipv6 addresses
23
+ sleep IPV4_DELAY_SECONDS if addr.ipv4?
24
+
25
+ # raises Errno::ECONNREFUSED when ip:port is unreachable
26
+ Socket.tcp(addr.ip_address, serv, connect_timeout: CONNECTION_TIMEOUT).close
27
+ mutex.synchronize do
28
+ addrs << addr.ip_address
29
+ cond_var.signal
30
+ end
31
+ end
32
+ end
33
+
34
+ mutex.synchronize do
35
+ timeout_time = CONNECTION_TIMEOUT + Time.now.to_f
36
+ while addrs.empty? && (remaining_time = timeout_time - Time.now.to_f) > 0
37
+ cond_var.wait(mutex, remaining_time)
38
+ end
39
+
40
+ host = addrs.shift unless addrs.empty?
41
+ end
42
+
43
+ super(host, serv, *rest)
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ TCPSocket.prepend CoreExtensions::TCPSocketExt
@@ -78,6 +78,7 @@ class Gem::RemoteFetcher
78
78
  # fetching the gem.
79
79
 
80
80
  def initialize(proxy=nil, dns=nil, headers={})
81
+ require 'rubygems/core_ext/tcpsocket_init' if Gem.configuration.ipv4_fallback_enabled
81
82
  require 'net/http'
82
83
  require 'stringio'
83
84
  require 'uri'
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "rubygems-update"
5
- s.version = "3.2.10"
5
+ s.version = "3.2.11"
6
6
  s.authors = ["Jim Weirich", "Chad Fowler", "Eric Hodel", "Luis Lavena", "Aaron Patterson", "Samuel Giddins", "André Arko", "Evan Phoenix", "Hiroshi SHIBATA"]
7
7
  s.email = ["", "", "drbrain@segment7.net", "luislavena@gmail.com", "aaron@tenderlovemaking.com", "segiddins@segiddins.me", "andre@arko.net", "evan@phx.io", "hsbt@ruby-lang.org"]
8
8
 
@@ -1958,9 +1958,15 @@ class TestGem < Gem::TestCase
1958
1958
  io.write 'gem "a"'
1959
1959
  end
1960
1960
 
1961
+ platform = Bundler::GemHelpers.generic_local_platform
1962
+ if platform == Gem::Platform::RUBY
1963
+ platform = ''
1964
+ else
1965
+ platform = " #{platform}"
1966
+ end
1967
+
1961
1968
  expected = <<-EXPECTED
1962
- Could not find gem 'a' in locally installed gems.
1963
- The source does not contain any versions of 'a'
1969
+ Could not find gem 'a#{platform}' in any of the gem sources listed in your Gemfile.
1964
1970
  You may need to `gem install -g` to install missing gems
1965
1971
 
1966
1972
  EXPECTED
@@ -41,6 +41,7 @@ class TestGemConfigFile < Gem::TestCase
41
41
  assert_equal true, @cfg.verbose
42
42
  assert_equal [@gem_repo], Gem.sources
43
43
  assert_equal 365, @cfg.cert_expiration_length_days
44
+ assert_equal false, @cfg.ipv4_fallback_enabled
44
45
 
45
46
  File.open @temp_conf, 'w' do |fp|
46
47
  fp.puts ":backtrace: true"
@@ -56,6 +57,7 @@ class TestGemConfigFile < Gem::TestCase
56
57
  fp.puts ":ssl_verify_mode: 0"
57
58
  fp.puts ":ssl_ca_cert: /etc/ssl/certs"
58
59
  fp.puts ":cert_expiration_length_days: 28"
60
+ fp.puts ":ipv4_fallback_enabled: true"
59
61
  end
60
62
 
61
63
  util_config_file
@@ -70,6 +72,14 @@ class TestGemConfigFile < Gem::TestCase
70
72
  assert_equal 0, @cfg.ssl_verify_mode
71
73
  assert_equal '/etc/ssl/certs', @cfg.ssl_ca_cert
72
74
  assert_equal 28, @cfg.cert_expiration_length_days
75
+ assert_equal true, @cfg.ipv4_fallback_enabled
76
+ end
77
+
78
+ def test_initialize_ipv4_fallback_enabled_env
79
+ ENV['IPV4_FALLBACK_ENABLED'] = 'true'
80
+ util_config_file %W[--config-file #{@temp_conf}]
81
+
82
+ assert_equal true, @cfg.ipv4_fallback_enabled
73
83
  end
74
84
 
75
85
  def test_initialize_handle_arguments_config_file
@@ -962,6 +962,12 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
962
962
  end
963
963
  end
964
964
 
965
+ def test_tcpsocketext_require
966
+ with_configured_fetcher(":ipv4_fallback_enabled: true") do |fetcher|
967
+ refute require('rubygems/core_ext/tcpsocket_init')
968
+ end
969
+ end
970
+
965
971
  def with_configured_fetcher(config_str = nil, &block)
966
972
  if config_str
967
973
  temp_conf = File.join @tempdir, '.gemrc'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubygems-update
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.10
4
+ version: 3.2.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jim Weirich
@@ -16,7 +16,7 @@ authors:
16
16
  autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
- date: 2021-02-15 00:00:00.000000000 Z
19
+ date: 2021-02-17 00:00:00.000000000 Z
20
20
  dependencies: []
21
21
  description: |-
22
22
  A package (also known as a library) contains a set of functionality
@@ -410,6 +410,7 @@ files:
410
410
  - lib/rubygems/core_ext/kernel_gem.rb
411
411
  - lib/rubygems/core_ext/kernel_require.rb
412
412
  - lib/rubygems/core_ext/kernel_warn.rb
413
+ - lib/rubygems/core_ext/tcpsocket_init.rb
413
414
  - lib/rubygems/defaults.rb
414
415
  - lib/rubygems/dependency.rb
415
416
  - lib/rubygems/dependency_installer.rb
@@ -767,7 +768,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
767
768
  - !ruby/object:Gem::Version
768
769
  version: '0'
769
770
  requirements: []
770
- rubygems_version: 3.2.10
771
+ rubygems_version: 3.2.11
771
772
  signing_key:
772
773
  specification_version: 4
773
774
  summary: RubyGems is a package management framework for Ruby.