rubygems-update 3.5.6 → 3.5.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +204 -1
  3. data/CODE_OF_CONDUCT.md +79 -28
  4. data/CONTRIBUTING.md +2 -2
  5. data/Manifest.txt +9 -4
  6. data/POLICIES.md +75 -6
  7. data/bundler/CHANGELOG.md +156 -0
  8. data/bundler/lib/bundler/build_metadata.rb +2 -2
  9. data/bundler/lib/bundler/cli/binstubs.rb +1 -1
  10. data/bundler/lib/bundler/cli/fund.rb +1 -1
  11. data/bundler/lib/bundler/cli/gem.rb +7 -14
  12. data/bundler/lib/bundler/cli/install.rb +1 -1
  13. data/bundler/lib/bundler/cli/plugin.rb +3 -2
  14. data/bundler/lib/bundler/cli.rb +14 -31
  15. data/bundler/lib/bundler/compact_index_client/cache.rb +47 -72
  16. data/bundler/lib/bundler/compact_index_client/parser.rb +84 -0
  17. data/bundler/lib/bundler/compact_index_client.rb +51 -80
  18. data/bundler/lib/bundler/constants.rb +8 -1
  19. data/bundler/lib/bundler/definition.rb +114 -71
  20. data/bundler/lib/bundler/dependency.rb +2 -1
  21. data/bundler/lib/bundler/dsl.rb +16 -1
  22. data/bundler/lib/bundler/endpoint_specification.rb +11 -0
  23. data/bundler/lib/bundler/env.rb +1 -1
  24. data/bundler/lib/bundler/environment_preserver.rb +2 -20
  25. data/bundler/lib/bundler/errors.rb +14 -0
  26. data/bundler/lib/bundler/fetcher/compact_index.rb +15 -24
  27. data/bundler/lib/bundler/gem_helper.rb +1 -1
  28. data/bundler/lib/bundler/gem_helpers.rb +14 -7
  29. data/bundler/lib/bundler/gem_version_promoter.rb +42 -38
  30. data/bundler/lib/bundler/injector.rb +3 -5
  31. data/bundler/lib/bundler/installer/gem_installer.rb +0 -1
  32. data/bundler/lib/bundler/installer/standalone.rb +0 -3
  33. data/bundler/lib/bundler/installer.rb +9 -11
  34. data/bundler/lib/bundler/lazy_specification.rb +1 -0
  35. data/bundler/lib/bundler/man/bundle-add.1 +1 -1
  36. data/bundler/lib/bundler/man/bundle-binstubs.1 +1 -1
  37. data/bundler/lib/bundler/man/bundle-cache.1 +1 -1
  38. data/bundler/lib/bundler/man/bundle-check.1 +3 -1
  39. data/bundler/lib/bundler/man/bundle-check.1.ronn +3 -0
  40. data/bundler/lib/bundler/man/bundle-clean.1 +1 -1
  41. data/bundler/lib/bundler/man/bundle-config.1 +2 -4
  42. data/bundler/lib/bundler/man/bundle-config.1.ronn +1 -4
  43. data/bundler/lib/bundler/man/bundle-console.1 +1 -1
  44. data/bundler/lib/bundler/man/bundle-doctor.1 +1 -1
  45. data/bundler/lib/bundler/man/bundle-exec.1 +1 -1
  46. data/bundler/lib/bundler/man/bundle-gem.1 +7 -1
  47. data/bundler/lib/bundler/man/bundle-gem.1.ronn +11 -0
  48. data/bundler/lib/bundler/man/bundle-help.1 +1 -1
  49. data/bundler/lib/bundler/man/bundle-info.1 +1 -1
  50. data/bundler/lib/bundler/man/bundle-init.1 +1 -1
  51. data/bundler/lib/bundler/man/bundle-inject.1 +1 -1
  52. data/bundler/lib/bundler/man/bundle-install.1 +3 -3
  53. data/bundler/lib/bundler/man/bundle-install.1.ronn +2 -2
  54. data/bundler/lib/bundler/man/bundle-list.1 +1 -1
  55. data/bundler/lib/bundler/man/bundle-lock.1 +1 -1
  56. data/bundler/lib/bundler/man/bundle-open.1 +1 -1
  57. data/bundler/lib/bundler/man/bundle-outdated.1 +1 -1
  58. data/bundler/lib/bundler/man/bundle-platform.1 +1 -1
  59. data/bundler/lib/bundler/man/bundle-plugin.1 +7 -4
  60. data/bundler/lib/bundler/man/bundle-plugin.1.ronn +7 -3
  61. data/bundler/lib/bundler/man/bundle-pristine.1 +1 -1
  62. data/bundler/lib/bundler/man/bundle-remove.1 +1 -1
  63. data/bundler/lib/bundler/man/bundle-show.1 +1 -1
  64. data/bundler/lib/bundler/man/bundle-update.1 +1 -1
  65. data/bundler/lib/bundler/man/bundle-version.1 +1 -1
  66. data/bundler/lib/bundler/man/bundle-viz.1 +1 -1
  67. data/bundler/lib/bundler/man/bundle.1 +1 -1
  68. data/bundler/lib/bundler/man/gemfile.5 +3 -3
  69. data/bundler/lib/bundler/man/gemfile.5.ronn +2 -2
  70. data/bundler/lib/bundler/plugin/installer/path.rb +18 -0
  71. data/bundler/lib/bundler/plugin/installer.rb +36 -16
  72. data/bundler/lib/bundler/plugin/source_list.rb +4 -4
  73. data/bundler/lib/bundler/resolver/base.rb +4 -0
  74. data/bundler/lib/bundler/resolver/candidate.rb +5 -17
  75. data/bundler/lib/bundler/resolver/package.rb +4 -0
  76. data/bundler/lib/bundler/resolver/spec_group.rb +20 -2
  77. data/bundler/lib/bundler/resolver.rb +72 -33
  78. data/bundler/lib/bundler/rubygems_ext.rb +98 -10
  79. data/bundler/lib/bundler/rubygems_gem_installer.rb +35 -2
  80. data/bundler/lib/bundler/rubygems_integration.rb +16 -2
  81. data/bundler/lib/bundler/runtime.rb +1 -1
  82. data/bundler/lib/bundler/self_manager.rb +22 -2
  83. data/bundler/lib/bundler/settings.rb +22 -16
  84. data/bundler/lib/bundler/setup.rb +6 -0
  85. data/bundler/lib/bundler/shared_helpers.rb +6 -4
  86. data/bundler/lib/bundler/source/git/git_proxy.rb +8 -0
  87. data/bundler/lib/bundler/source/git.rb +14 -0
  88. data/bundler/lib/bundler/source/metadata.rb +2 -0
  89. data/bundler/lib/bundler/source/path.rb +0 -13
  90. data/bundler/lib/bundler/source/rubygems.rb +31 -30
  91. data/bundler/lib/bundler/source_list.rb +26 -2
  92. data/bundler/lib/bundler/spec_set.rb +15 -13
  93. data/bundler/lib/bundler/stub_specification.rb +8 -0
  94. data/bundler/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +77 -29
  95. data/bundler/lib/bundler/templates/newgem/newgem.gemspec.tt +4 -3
  96. data/bundler/lib/bundler/templates/newgem/rubocop.yml.tt +0 -5
  97. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb +1 -0
  98. data/bundler/lib/bundler/vendored_net_http.rb +20 -5
  99. data/bundler/lib/bundler/vendored_timeout.rb +7 -3
  100. data/bundler/lib/bundler/version.rb +1 -1
  101. data/bundler/lib/bundler/yaml_serializer.rb +1 -8
  102. data/bundler/lib/bundler.rb +26 -1
  103. data/exe/update_rubygems +1 -1
  104. data/lib/rubygems/basic_specification.rb +27 -0
  105. data/lib/rubygems/bundler_version_finder.rb +1 -1
  106. data/lib/rubygems/command.rb +1 -1
  107. data/lib/rubygems/command_manager.rb +2 -1
  108. data/lib/rubygems/commands/build_command.rb +2 -11
  109. data/lib/rubygems/commands/help_command.rb +2 -2
  110. data/lib/rubygems/commands/pristine_command.rb +12 -9
  111. data/lib/rubygems/commands/rdoc_command.rb +1 -8
  112. data/lib/rubygems/commands/rebuild_command.rb +264 -0
  113. data/lib/rubygems/commands/setup_command.rb +2 -0
  114. data/lib/rubygems/commands/uninstall_command.rb +1 -1
  115. data/lib/rubygems/commands/update_command.rb +8 -9
  116. data/lib/rubygems/config_file.rb +33 -16
  117. data/lib/rubygems/defaults.rb +4 -4
  118. data/lib/rubygems/dependency.rb +3 -15
  119. data/lib/rubygems/dependency_list.rb +1 -1
  120. data/lib/rubygems/deprecate.rb +79 -77
  121. data/lib/rubygems/ext/cargo_builder.rb +2 -17
  122. data/lib/rubygems/gemcutter_utilities/webauthn_poller.rb +3 -1
  123. data/lib/rubygems/gemcutter_utilities.rb +1 -1
  124. data/lib/rubygems/gemspec_helpers.rb +19 -0
  125. data/lib/rubygems/installer.rb +9 -8
  126. data/lib/rubygems/package/tar_header.rb +20 -4
  127. data/lib/rubygems/package.rb +13 -8
  128. data/lib/rubygems/platform.rb +3 -2
  129. data/lib/rubygems/remote_fetcher.rb +1 -1
  130. data/lib/rubygems/request.rb +1 -1
  131. data/lib/rubygems/request_set.rb +1 -1
  132. data/lib/rubygems/requirement.rb +2 -2
  133. data/lib/rubygems/resolver/spec_specification.rb +7 -0
  134. data/lib/rubygems/s3_uri_signer.rb +1 -1
  135. data/lib/rubygems/safe_yaml.rb +10 -1
  136. data/lib/rubygems/security.rb +1 -1
  137. data/lib/rubygems/specification.rb +55 -124
  138. data/lib/rubygems/specification_policy.rb +26 -6
  139. data/lib/rubygems/specification_record.rb +212 -0
  140. data/lib/rubygems/stub_specification.rb +21 -0
  141. data/lib/rubygems/uninstaller.rb +27 -20
  142. data/lib/rubygems/util/licenses.rb +68 -0
  143. data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph.rb +1 -1
  144. data/lib/rubygems/vendored_net_http.rb +5 -0
  145. data/lib/rubygems/vendored_timeout.rb +5 -0
  146. data/lib/rubygems/yaml_serializer.rb +1 -8
  147. data/lib/rubygems.rb +28 -15
  148. data/rubygems-update.gemspec +1 -1
  149. metadata +12 -7
  150. data/lib/rubygems/net/http.rb +0 -3
  151. data/lib/rubygems/timeout.rb +0 -3
  152. /data/lib/rubygems/{optparse.rb → vendored_optparse.rb} +0 -0
  153. /data/lib/rubygems/{tsort.rb → vendored_tsort.rb} +0 -0
@@ -11,6 +11,7 @@ require_relative "deprecate"
11
11
  require_relative "basic_specification"
12
12
  require_relative "stub_specification"
13
13
  require_relative "platform"
14
+ require_relative "specification_record"
14
15
  require_relative "util/list"
15
16
 
16
17
  require "rbconfig"
@@ -174,27 +175,17 @@ class Gem::Specification < Gem::BasicSpecification
174
175
  end
175
176
 
176
177
  @@attributes = @@default_value.keys.sort_by(&:to_s)
177
- @@array_attributes = @@default_value.reject {|_k,v| v != [] }.keys
178
+ @@array_attributes = @@default_value.select {|_k,v| v.is_a?(Array) }.keys
178
179
  @@nil_attributes, @@non_nil_attributes = @@default_value.keys.partition do |k|
179
180
  @@default_value[k].nil?
180
181
  end
181
182
 
182
- def self.clear_specs # :nodoc:
183
- @@all = nil
184
- @@stubs = nil
185
- @@stubs_by_name = {}
186
- @@spec_with_requirable_file = {}
187
- @@active_stub_with_requirable_file = {}
188
- end
189
- private_class_method :clear_specs
190
-
191
- clear_specs
192
-
193
183
  # Sentinel object to represent "not found" stubs
194
184
  NOT_FOUND = Struct.new(:to_spec, :this).new # :nodoc:
185
+ deprecate_constant :NOT_FOUND
195
186
 
196
187
  # Tracking removed method calls to warn users during build time.
197
- REMOVED_METHODS = [:rubyforge_project=].freeze # :nodoc:
188
+ REMOVED_METHODS = [:rubyforge_project=, :mark_version].freeze # :nodoc:
198
189
  def removed_method_calls
199
190
  @removed_method_calls ||= []
200
191
  end
@@ -341,7 +332,7 @@ class Gem::Specification < Gem::BasicSpecification
341
332
  # https://opensource.org/licenses/ approved.
342
333
  #
343
334
  # The most commonly used OSI-approved licenses are MIT and Apache-2.0.
344
- # GitHub also provides a license picker at http://choosealicense.com/.
335
+ # GitHub also provides a license picker at https://choosealicense.com/.
345
336
  #
346
337
  # You can also use a custom license file along with your gemspec and specify
347
338
  # a LicenseRef-<idstring>, where idstring is the name of the file containing
@@ -555,9 +546,9 @@ class Gem::Specification < Gem::BasicSpecification
555
546
  #
556
547
  # Usage:
557
548
  #
558
- # spec.add_runtime_dependency 'example', '~> 1.1', '>= 1.1.4'
549
+ # spec.add_dependency 'example', '~> 1.1', '>= 1.1.4'
559
550
 
560
- def add_runtime_dependency(gem, *requirements)
551
+ def add_dependency(gem, *requirements)
561
552
  if requirements.uniq.size != requirements.size
562
553
  warn "WARNING: duplicated #{gem} dependency #{requirements}"
563
554
  end
@@ -770,7 +761,7 @@ class Gem::Specification < Gem::BasicSpecification
770
761
  attr_accessor :specification_version
771
762
 
772
763
  def self._all # :nodoc:
773
- @@all ||= Gem.loaded_specs.values | stubs.map(&:to_spec)
764
+ specification_record.all
774
765
  end
775
766
 
776
767
  def self.clear_load_cache # :nodoc:
@@ -780,6 +771,11 @@ class Gem::Specification < Gem::BasicSpecification
780
771
  end
781
772
  private_class_method :clear_load_cache
782
773
 
774
+ def self.gem_path # :nodoc:
775
+ Gem.path
776
+ end
777
+ private_class_method :gem_path
778
+
783
779
  def self.each_gemspec(dirs) # :nodoc:
784
780
  dirs.each do |dir|
785
781
  Gem::Util.glob_files_in_dir("*.gemspec", dir).each do |path|
@@ -788,26 +784,9 @@ class Gem::Specification < Gem::BasicSpecification
788
784
  end
789
785
  end
790
786
 
791
- def self.gemspec_stubs_in(dir, pattern)
787
+ def self.gemspec_stubs_in(dir, pattern) # :nodoc:
792
788
  Gem::Util.glob_files_in_dir(pattern, dir).map {|path| yield path }.select(&:valid?)
793
789
  end
794
- private_class_method :gemspec_stubs_in
795
-
796
- def self.installed_stubs(dirs, pattern)
797
- map_stubs(dirs, pattern) do |path, base_dir, gems_dir|
798
- Gem::StubSpecification.gemspec_stub(path, base_dir, gems_dir)
799
- end
800
- end
801
- private_class_method :installed_stubs
802
-
803
- def self.map_stubs(dirs, pattern) # :nodoc:
804
- dirs.flat_map do |dir|
805
- base_dir = File.dirname dir
806
- gems_dir = File.join base_dir, "gems"
807
- gemspec_stubs_in(dir, pattern) {|path| yield path, base_dir, gems_dir }
808
- end
809
- end
810
- private_class_method :map_stubs
811
790
 
812
791
  def self.each_spec(dirs) # :nodoc:
813
792
  each_gemspec(dirs) do |path|
@@ -820,13 +799,7 @@ class Gem::Specification < Gem::BasicSpecification
820
799
  # Returns a Gem::StubSpecification for every installed gem
821
800
 
822
801
  def self.stubs
823
- @@stubs ||= begin
824
- pattern = "*.gemspec"
825
- stubs = stubs_for_pattern(pattern, false)
826
-
827
- @@stubs_by_name = stubs.select {|s| Gem::Platform.match_spec? s }.group_by(&:name)
828
- stubs
829
- end
802
+ specification_record.stubs
830
803
  end
831
804
 
832
805
  ##
@@ -845,13 +818,7 @@ class Gem::Specification < Gem::BasicSpecification
845
818
  # only returns stubs that match Gem.platforms
846
819
 
847
820
  def self.stubs_for(name)
848
- if @@stubs
849
- @@stubs_by_name[name] || []
850
- else
851
- @@stubs_by_name[name] ||= stubs_for_pattern("#{name}-*.gemspec").select do |s|
852
- s.name == name
853
- end
854
- end
821
+ specification_record.stubs_for(name)
855
822
  end
856
823
 
857
824
  ##
@@ -859,12 +826,7 @@ class Gem::Specification < Gem::BasicSpecification
859
826
  # optionally filtering out specs not matching the current platform
860
827
  #
861
828
  def self.stubs_for_pattern(pattern, match_platform = true) # :nodoc:
862
- installed_stubs = installed_stubs(Gem::Specification.dirs, pattern)
863
- installed_stubs.select! {|s| Gem::Platform.match_spec? s } if match_platform
864
- stubs = installed_stubs + default_stubs(pattern)
865
- stubs = stubs.uniq(&:full_name)
866
- _resort!(stubs)
867
- stubs
829
+ specification_record.stubs_for_pattern(pattern, match_platform)
868
830
  end
869
831
 
870
832
  def self._resort!(specs) # :nodoc:
@@ -873,7 +835,11 @@ class Gem::Specification < Gem::BasicSpecification
873
835
  next names if names.nonzero?
874
836
  versions = b.version <=> a.version
875
837
  next versions if versions.nonzero?
876
- Gem::Platform.sort_priority(b.platform)
838
+ platforms = Gem::Platform.sort_priority(b.platform) <=> Gem::Platform.sort_priority(a.platform)
839
+ next platforms if platforms.nonzero?
840
+ default_gem = a.default_gem_priority <=> b.default_gem_priority
841
+ next default_gem if default_gem.nonzero?
842
+ a.base_dir_priority(gem_path) <=> b.base_dir_priority(gem_path)
877
843
  end
878
844
  end
879
845
 
@@ -893,23 +859,14 @@ class Gem::Specification < Gem::BasicSpecification
893
859
  # properly sorted.
894
860
 
895
861
  def self.add_spec(spec)
896
- return if _all.include? spec
897
-
898
- _all << spec
899
- stubs << spec
900
- (@@stubs_by_name[spec.name] ||= []) << spec
901
-
902
- _resort!(@@stubs_by_name[spec.name])
903
- _resort!(stubs)
862
+ specification_record.add_spec(spec)
904
863
  end
905
864
 
906
865
  ##
907
866
  # Removes +spec+ from the known specs.
908
867
 
909
868
  def self.remove_spec(spec)
910
- _all.delete spec.to_spec
911
- stubs.delete spec
912
- (@@stubs_by_name[spec.name] || []).delete spec
869
+ specification_record.remove_spec(spec)
913
870
  end
914
871
 
915
872
  ##
@@ -917,33 +874,23 @@ class Gem::Specification < Gem::BasicSpecification
917
874
  # You probably want to use one of the Enumerable methods instead.
918
875
 
919
876
  def self.all
920
- warn "NOTE: Specification.all called from #{caller.first}" unless
877
+ warn "NOTE: Specification.all called from #{caller(1, 1).first}" unless
921
878
  Gem::Deprecate.skip
922
879
  _all
923
880
  end
924
881
 
925
882
  ##
926
- # Sets the known specs to +specs+. Not guaranteed to work for you in
927
- # the future. Use at your own risk. Caveat emptor. Doomy doom doom.
928
- # Etc etc.
929
- #
930
- #--
931
- # Makes +specs+ the known specs
932
- # Listen, time is a river
933
- # Winter comes, code breaks
934
- #
935
- # -- wilsonb
883
+ # Sets the known specs to +specs+.
936
884
 
937
885
  def self.all=(specs)
938
- @@stubs_by_name = specs.group_by(&:name)
939
- @@all = @@stubs = specs
886
+ specification_record.all = specs
940
887
  end
941
888
 
942
889
  ##
943
890
  # Return full names of all specs in sorted order.
944
891
 
945
892
  def self.all_names
946
- _all.map(&:full_name)
893
+ specification_record.all_names
947
894
  end
948
895
 
949
896
  ##
@@ -968,9 +915,7 @@ class Gem::Specification < Gem::BasicSpecification
968
915
  # Return the directories that Specification uses to find specs.
969
916
 
970
917
  def self.dirs
971
- @@dirs ||= Gem.path.collect do |dir|
972
- File.join dir, "specifications"
973
- end
918
+ @@dirs ||= Gem::SpecificationRecord.dirs_from(gem_path)
974
919
  end
975
920
 
976
921
  ##
@@ -980,7 +925,7 @@ class Gem::Specification < Gem::BasicSpecification
980
925
  def self.dirs=(dirs)
981
926
  reset
982
927
 
983
- @@dirs = Array(dirs).map {|dir| File.join dir, "specifications" }
928
+ @@dirs = Gem::SpecificationRecord.dirs_from(Array(dirs))
984
929
  end
985
930
 
986
931
  extend Enumerable
@@ -989,21 +934,15 @@ class Gem::Specification < Gem::BasicSpecification
989
934
  # Enumerate every known spec. See ::dirs= and ::add_spec to set the list of
990
935
  # specs.
991
936
 
992
- def self.each
993
- return enum_for(:each) unless block_given?
994
-
995
- _all.each do |x|
996
- yield x
997
- end
937
+ def self.each(&block)
938
+ specification_record.each(&block)
998
939
  end
999
940
 
1000
941
  ##
1001
942
  # Returns every spec that matches +name+ and optional +requirements+.
1002
943
 
1003
944
  def self.find_all_by_name(name, *requirements)
1004
- requirements = Gem::Requirement.default if requirements.empty?
1005
-
1006
- Gem::Dependency.new(name, *requirements).matching_specs
945
+ specification_record.find_all_by_name(name, *requirements)
1007
946
  end
1008
947
 
1009
948
  ##
@@ -1033,12 +972,7 @@ class Gem::Specification < Gem::BasicSpecification
1033
972
  # Return the best specification that contains the file matching +path+.
1034
973
 
1035
974
  def self.find_by_path(path)
1036
- path = path.dup.freeze
1037
- spec = @@spec_with_requirable_file[path] ||= stubs.find do |s|
1038
- s.contains_requirable_file? path
1039
- end || NOT_FOUND
1040
-
1041
- spec.to_spec
975
+ specification_record.find_by_path(path)
1042
976
  end
1043
977
 
1044
978
  ##
@@ -1046,19 +980,15 @@ class Gem::Specification < Gem::BasicSpecification
1046
980
  # amongst the specs that are not activated.
1047
981
 
1048
982
  def self.find_inactive_by_path(path)
1049
- stub = stubs.find do |s|
1050
- next if s.activated?
1051
- s.contains_requirable_file? path
1052
- end
1053
- stub&.to_spec
983
+ specification_record.find_inactive_by_path(path)
1054
984
  end
1055
985
 
1056
- def self.find_active_stub_by_path(path)
1057
- stub = @@active_stub_with_requirable_file[path] ||= stubs.find do |s|
1058
- s.activated? && s.contains_requirable_file?(path)
1059
- end || NOT_FOUND
986
+ ##
987
+ # Return the best specification that contains the file matching +path+, among
988
+ # those already activated.
1060
989
 
1061
- stub.this
990
+ def self.find_active_stub_by_path(path)
991
+ specification_record.find_active_stub_by_path(path)
1062
992
  end
1063
993
 
1064
994
  ##
@@ -1125,14 +1055,14 @@ class Gem::Specification < Gem::BasicSpecification
1125
1055
  # +prerelease+ is true.
1126
1056
 
1127
1057
  def self.latest_specs(prerelease = false)
1128
- _latest_specs Gem::Specification.stubs, prerelease
1058
+ specification_record.latest_specs(prerelease)
1129
1059
  end
1130
1060
 
1131
1061
  ##
1132
1062
  # Return the latest installed spec for gem +name+.
1133
1063
 
1134
1064
  def self.latest_spec_for(name)
1135
- latest_specs(true).find {|installed_spec| installed_spec.name == name }
1065
+ specification_record.latest_spec_for(name)
1136
1066
  end
1137
1067
 
1138
1068
  def self._latest_specs(specs, prerelease = false) # :nodoc:
@@ -1270,7 +1200,7 @@ class Gem::Specification < Gem::BasicSpecification
1270
1200
  def self.reset
1271
1201
  @@dirs = nil
1272
1202
  Gem.pre_reset_hooks.each(&:call)
1273
- clear_specs
1203
+ @specification_record = nil
1274
1204
  clear_load_cache
1275
1205
  unresolved = unresolved_deps
1276
1206
  unless unresolved.empty?
@@ -1291,6 +1221,13 @@ class Gem::Specification < Gem::BasicSpecification
1291
1221
  Gem.post_reset_hooks.each(&:call)
1292
1222
  end
1293
1223
 
1224
+ ##
1225
+ # Keeps track of all currently known specifications
1226
+
1227
+ def self.specification_record
1228
+ @specification_record ||= Gem::SpecificationRecord.new(dirs)
1229
+ end
1230
+
1294
1231
  # DOC: This method needs documented or nodoc'd
1295
1232
  def self.unresolved_deps
1296
1233
  @unresolved_deps ||= Hash.new {|h, n| h[n] = Gem::Dependency.new n }
@@ -1567,7 +1504,7 @@ class Gem::Specification < Gem::BasicSpecification
1567
1504
 
1568
1505
  private :add_dependency_with_type
1569
1506
 
1570
- alias_method :add_dependency, :add_runtime_dependency
1507
+ alias_method :add_runtime_dependency, :add_dependency
1571
1508
 
1572
1509
  ##
1573
1510
  # Adds this spec's require paths to LOAD_PATH, in the proper location.
@@ -1874,8 +1811,6 @@ class Gem::Specification < Gem::BasicSpecification
1874
1811
  end
1875
1812
 
1876
1813
  def encode_with(coder) # :nodoc:
1877
- mark_version
1878
-
1879
1814
  coder.add "name", @name
1880
1815
  coder.add "version", @version
1881
1816
  platform = case @original_platform
@@ -2169,13 +2104,6 @@ class Gem::Specification < Gem::BasicSpecification
2169
2104
  @spec_file = nil
2170
2105
  end
2171
2106
 
2172
- ##
2173
- # Sets the rubygems_version to the current RubyGems version.
2174
-
2175
- def mark_version
2176
- @rubygems_version = Gem::VERSION
2177
- end
2178
-
2179
2107
  ##
2180
2108
  # Track removed method calls to warn about during build time.
2181
2109
  # Warn about unknown attributes while loading a spec.
@@ -2493,7 +2421,6 @@ class Gem::Specification < Gem::BasicSpecification
2493
2421
  # still have their default values are omitted.
2494
2422
 
2495
2423
  def to_ruby
2496
- mark_version
2497
2424
  result = []
2498
2425
  result << "# -*- encoding: utf-8 -*-"
2499
2426
  result << "#{Gem::StubSpecification::PREFIX}#{name} #{version} #{platform} #{raw_require_paths.join("\0")}"
@@ -2658,6 +2585,10 @@ class Gem::Specification < Gem::BasicSpecification
2658
2585
  @test_files.delete_if {|x| File.directory?(x) && !File.symlink?(x) }
2659
2586
  end
2660
2587
 
2588
+ def validate_for_resolution
2589
+ Gem::SpecificationPolicy.new(self).validate_for_resolution
2590
+ end
2591
+
2661
2592
  def validate_metadata
2662
2593
  Gem::SpecificationPolicy.new(self).validate_metadata
2663
2594
  end
@@ -7,7 +7,7 @@ class Gem::SpecificationPolicy
7
7
 
8
8
  VALID_NAME_PATTERN = /\A[a-zA-Z0-9\.\-\_]+\z/ # :nodoc:
9
9
 
10
- SPECIAL_CHARACTERS = /\A[#{Regexp.escape('.-_')}]+/ # :nodoc:
10
+ SPECIAL_CHARACTERS = /\A[#{Regexp.escape(".-_")}]+/ # :nodoc:
11
11
 
12
12
  VALID_URI_PATTERN = %r{\Ahttps?:\/\/([^\s:@]+:[^\s:@]*@)?[A-Za-z\d\-]+(\.[A-Za-z\d\-]+)+\.?(:\d{1,5})?([\/?]\S*)?\z} # :nodoc:
13
13
 
@@ -45,6 +45,7 @@ class Gem::SpecificationPolicy
45
45
 
46
46
  def validate(strict = false)
47
47
  validate_required!
48
+ validate_required_metadata!
48
49
 
49
50
  validate_optional(strict) if packaging || strict
50
51
 
@@ -85,15 +86,17 @@ class Gem::SpecificationPolicy
85
86
 
86
87
  validate_authors_field
87
88
 
88
- validate_metadata
89
-
90
89
  validate_licenses_length
91
90
 
92
- validate_lazy_metadata
93
-
94
91
  validate_duplicate_dependencies
95
92
  end
96
93
 
94
+ def validate_required_metadata!
95
+ validate_metadata
96
+
97
+ validate_lazy_metadata
98
+ end
99
+
97
100
  def validate_optional(strict)
98
101
  validate_licenses
99
102
 
@@ -103,6 +106,8 @@ class Gem::SpecificationPolicy
103
106
 
104
107
  validate_dependencies
105
108
 
109
+ validate_required_ruby_version
110
+
106
111
  validate_extensions
107
112
 
108
113
  validate_removed_attributes
@@ -118,6 +123,13 @@ class Gem::SpecificationPolicy
118
123
  end
119
124
  end
120
125
 
126
+ ##
127
+ # Implementation for Specification#validate_for_resolution
128
+
129
+ def validate_for_resolution
130
+ validate_required!
131
+ end
132
+
121
133
  ##
122
134
  # Implementation for Specification#validate_metadata
123
135
 
@@ -227,6 +239,12 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
227
239
  end
228
240
  end
229
241
 
242
+ def validate_required_ruby_version
243
+ if @specification.required_ruby_version.requirements == [Gem::Requirement::DefaultRequirement]
244
+ warning "make sure you specify the oldest ruby version constraint (like \">= 3.0\") that you want your gem to support by setting the `required_ruby_version` gemspec attribute"
245
+ end
246
+ end
247
+
230
248
  ##
231
249
  # Issues a warning for each file to be packaged which is world-readable.
232
250
  #
@@ -266,7 +284,9 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
266
284
 
267
285
  return if rubygems_version == Gem::VERSION
268
286
 
269
- error "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}"
287
+ warning "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}"
288
+
289
+ @specification.rubygems_version = Gem::VERSION
270
290
  end
271
291
 
272
292
  def validate_required_attributes
@@ -0,0 +1,212 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gem
4
+ class SpecificationRecord
5
+ def self.dirs_from(paths)
6
+ paths.map do |path|
7
+ File.join(path, "specifications")
8
+ end
9
+ end
10
+
11
+ def self.from_path(path)
12
+ new(dirs_from([path]))
13
+ end
14
+
15
+ def initialize(dirs)
16
+ @all = nil
17
+ @stubs = nil
18
+ @stubs_by_name = {}
19
+ @spec_with_requirable_file = {}
20
+ @active_stub_with_requirable_file = {}
21
+
22
+ @dirs = dirs
23
+ end
24
+
25
+ # Sentinel object to represent "not found" stubs
26
+ NOT_FOUND = Struct.new(:to_spec, :this).new
27
+ private_constant :NOT_FOUND
28
+
29
+ ##
30
+ # Returns the list of all specifications in the record
31
+
32
+ def all
33
+ @all ||= Gem.loaded_specs.values | stubs.map(&:to_spec)
34
+ end
35
+
36
+ ##
37
+ # Returns a Gem::StubSpecification for every specification in the record
38
+
39
+ def stubs
40
+ @stubs ||= begin
41
+ pattern = "*.gemspec"
42
+ stubs = stubs_for_pattern(pattern, false)
43
+
44
+ @stubs_by_name = stubs.select {|s| Gem::Platform.match_spec? s }.group_by(&:name)
45
+ stubs
46
+ end
47
+ end
48
+
49
+ ##
50
+ # Returns a Gem::StubSpecification for every specification in the record
51
+ # named +name+ only returns stubs that match Gem.platforms
52
+
53
+ def stubs_for(name)
54
+ if @stubs
55
+ @stubs_by_name[name] || []
56
+ else
57
+ @stubs_by_name[name] ||= stubs_for_pattern("#{name}-*.gemspec").select do |s|
58
+ s.name == name
59
+ end
60
+ end
61
+ end
62
+
63
+ ##
64
+ # Finds stub specifications matching a pattern in the record, optionally
65
+ # filtering out specs not matching the current platform
66
+
67
+ def stubs_for_pattern(pattern, match_platform = true)
68
+ installed_stubs = installed_stubs(pattern)
69
+ installed_stubs.select! {|s| Gem::Platform.match_spec? s } if match_platform
70
+ stubs = installed_stubs + Gem::Specification.default_stubs(pattern)
71
+ Gem::Specification._resort!(stubs)
72
+ stubs
73
+ end
74
+
75
+ ##
76
+ # Adds +spec+ to the the record, keeping the collection properly sorted.
77
+
78
+ def add_spec(spec)
79
+ return if all.include? spec
80
+
81
+ all << spec
82
+ stubs << spec
83
+ (@stubs_by_name[spec.name] ||= []) << spec
84
+
85
+ Gem::Specification._resort!(@stubs_by_name[spec.name])
86
+ Gem::Specification._resort!(stubs)
87
+ end
88
+
89
+ ##
90
+ # Removes +spec+ from the record.
91
+
92
+ def remove_spec(spec)
93
+ all.delete spec.to_spec
94
+ stubs.delete spec
95
+ (@stubs_by_name[spec.name] || []).delete spec
96
+ end
97
+
98
+ ##
99
+ # Sets the specs known by the record to +specs+.
100
+
101
+ def all=(specs)
102
+ @stubs_by_name = specs.group_by(&:name)
103
+ @all = @stubs = specs
104
+ end
105
+
106
+ ##
107
+ # Return full names of all specs in the record in sorted order.
108
+
109
+ def all_names
110
+ all.map(&:full_name)
111
+ end
112
+
113
+ include Enumerable
114
+
115
+ ##
116
+ # Enumerate every known spec.
117
+
118
+ def each
119
+ return enum_for(:each) unless block_given?
120
+
121
+ all.each do |x|
122
+ yield x
123
+ end
124
+ end
125
+
126
+ ##
127
+ # Returns every spec in the record that matches +name+ and optional +requirements+.
128
+
129
+ def find_all_by_name(name, *requirements)
130
+ req = Gem::Requirement.create(*requirements)
131
+ env_req = Gem.env_requirement(name)
132
+
133
+ matches = stubs_for(name).find_all do |spec|
134
+ req.satisfied_by?(spec.version) && env_req.satisfied_by?(spec.version)
135
+ end.map(&:to_spec)
136
+
137
+ if name == "bundler" && !req.specific?
138
+ require_relative "bundler_version_finder"
139
+ Gem::BundlerVersionFinder.prioritize!(matches)
140
+ end
141
+
142
+ matches
143
+ end
144
+
145
+ ##
146
+ # Return the best specification in the record that contains the file matching +path+.
147
+
148
+ def find_by_path(path)
149
+ path = path.dup.freeze
150
+ spec = @spec_with_requirable_file[path] ||= stubs.find do |s|
151
+ s.contains_requirable_file? path
152
+ end || NOT_FOUND
153
+
154
+ spec.to_spec
155
+ end
156
+
157
+ ##
158
+ # Return the best specification in the record that contains the file
159
+ # matching +path+ amongst the specs that are not activated.
160
+
161
+ def find_inactive_by_path(path)
162
+ stub = stubs.find do |s|
163
+ next if s.activated?
164
+ s.contains_requirable_file? path
165
+ end
166
+ stub&.to_spec
167
+ end
168
+
169
+ ##
170
+ # Return the best specification in the record that contains the file
171
+ # matching +path+, among those already activated.
172
+
173
+ def find_active_stub_by_path(path)
174
+ stub = @active_stub_with_requirable_file[path] ||= stubs.find do |s|
175
+ s.activated? && s.contains_requirable_file?(path)
176
+ end || NOT_FOUND
177
+
178
+ stub.this
179
+ end
180
+
181
+ ##
182
+ # Return the latest specs in the record, optionally including prerelease
183
+ # specs if +prerelease+ is true.
184
+
185
+ def latest_specs(prerelease)
186
+ Gem::Specification._latest_specs stubs, prerelease
187
+ end
188
+
189
+ ##
190
+ # Return the latest installed spec in the record for gem +name+.
191
+
192
+ def latest_spec_for(name)
193
+ latest_specs(true).find {|installed_spec| installed_spec.name == name }
194
+ end
195
+
196
+ private
197
+
198
+ def installed_stubs(pattern)
199
+ map_stubs(pattern) do |path, base_dir, gems_dir|
200
+ Gem::StubSpecification.gemspec_stub(path, base_dir, gems_dir)
201
+ end
202
+ end
203
+
204
+ def map_stubs(pattern)
205
+ @dirs.flat_map do |dir|
206
+ base_dir = File.dirname dir
207
+ gems_dir = File.join base_dir, "gems"
208
+ Gem::Specification.gemspec_stubs_in(dir, pattern) {|path| yield path, base_dir, gems_dir }
209
+ end
210
+ end
211
+ end
212
+ end