rubygems-update 2.4.8 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rubygems-update might be problematic. Click here for more details.

Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CODE_OF_CONDUCT.md +40 -0
  5. data/CVE-2015-3900.txt +40 -0
  6. data/History.txt +173 -2
  7. data/Manifest.txt +14 -1
  8. data/Rakefile +36 -1
  9. data/lib/rubygems.rb +32 -14
  10. data/lib/rubygems/basic_specification.rb +31 -9
  11. data/lib/rubygems/commands/dependency_command.rb +25 -15
  12. data/lib/rubygems/commands/environment_command.rb +2 -0
  13. data/lib/rubygems/commands/help_command.rb +0 -10
  14. data/lib/rubygems/commands/install_command.rb +1 -1
  15. data/lib/rubygems/commands/list_command.rb +1 -1
  16. data/lib/rubygems/commands/pristine_command.rb +11 -1
  17. data/lib/rubygems/commands/query_command.rb +1 -1
  18. data/lib/rubygems/commands/sources_command.rb +1 -1
  19. data/lib/rubygems/commands/update_command.rb +2 -2
  20. data/lib/rubygems/config_file.rb +4 -4
  21. data/lib/rubygems/core_ext/kernel_require.rb +2 -2
  22. data/lib/rubygems/dependency.rb +9 -6
  23. data/lib/rubygems/dependency_list.rb +3 -0
  24. data/lib/rubygems/ext/builder.rb +2 -0
  25. data/lib/rubygems/ext/ext_conf_builder.rb +6 -1
  26. data/lib/rubygems/indexer.rb +26 -91
  27. data/lib/rubygems/installer.rb +58 -26
  28. data/lib/rubygems/installer_test_case.rb +2 -2
  29. data/lib/rubygems/package.rb +18 -6
  30. data/lib/rubygems/package/old.rb +2 -2
  31. data/lib/rubygems/package/tar_reader/entry.rb +7 -1
  32. data/lib/rubygems/package/tar_test_case.rb +12 -3
  33. data/lib/rubygems/package/tar_writer.rb +19 -1
  34. data/lib/rubygems/platform.rb +3 -2
  35. data/lib/rubygems/rdoc.rb +1 -2
  36. data/lib/rubygems/remote_fetcher.rb +25 -6
  37. data/lib/rubygems/request/connection_pools.rb +8 -4
  38. data/lib/rubygems/request_set.rb +3 -4
  39. data/lib/rubygems/request_set/gem_dependency_api.rb +2 -2
  40. data/lib/rubygems/request_set/lockfile.rb +1 -1
  41. data/lib/rubygems/request_set/lockfile/parser.rb +54 -43
  42. data/lib/rubygems/request_set/lockfile/tokenizer.rb +16 -13
  43. data/lib/rubygems/resolver.rb +47 -242
  44. data/lib/rubygems/resolver/activation_request.rb +2 -1
  45. data/lib/rubygems/resolver/conflict.rb +0 -1
  46. data/lib/rubygems/resolver/dependency_request.rb +4 -1
  47. data/lib/rubygems/resolver/git_specification.rb +1 -2
  48. data/lib/rubygems/resolver/molinillo.rb +1 -0
  49. data/lib/rubygems/resolver/molinillo/lib/molinillo.rb +5 -0
  50. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb +266 -0
  51. data/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb +69 -0
  52. data/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb +3 -0
  53. data/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb +99 -0
  54. data/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb +63 -0
  55. data/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb +430 -0
  56. data/lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb +43 -0
  57. data/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb +51 -0
  58. data/lib/rubygems/resolver/specification.rb +1 -1
  59. data/lib/rubygems/specification.rb +256 -86
  60. data/lib/rubygems/stub_specification.rb +37 -29
  61. data/lib/rubygems/test_case.rb +65 -28
  62. data/lib/rubygems/test_utilities.rb +18 -18
  63. data/lib/rubygems/text.rb +0 -2
  64. data/lib/rubygems/uninstaller.rb +1 -1
  65. data/lib/rubygems/util.rb +4 -4
  66. data/lib/rubygems/util/licenses.rb +309 -0
  67. data/lib/rubygems/util/list.rb +9 -21
  68. data/lib/rubygems/version.rb +24 -14
  69. data/test/rubygems/simple_gem.rb +1 -1
  70. data/test/rubygems/test_config.rb +10 -1
  71. data/test/rubygems/test_gem.rb +58 -11
  72. data/test/rubygems/test_gem_available_set.rb +2 -1
  73. data/test/rubygems/test_gem_commands_cleanup_command.rb +6 -5
  74. data/test/rubygems/test_gem_commands_dependency_command.rb +9 -1
  75. data/test/rubygems/test_gem_commands_install_command.rb +17 -28
  76. data/test/rubygems/test_gem_commands_mirror.rb +0 -13
  77. data/test/rubygems/test_gem_commands_outdated_command.rb +2 -3
  78. data/test/rubygems/test_gem_commands_pristine_command.rb +33 -5
  79. data/test/rubygems/test_gem_commands_query_command.rb +123 -158
  80. data/test/rubygems/test_gem_commands_server_command.rb +2 -2
  81. data/test/rubygems/test_gem_commands_specification_command.rb +4 -4
  82. data/test/rubygems/test_gem_commands_stale_command.rb +2 -0
  83. data/test/rubygems/test_gem_commands_uninstall_command.rb +5 -4
  84. data/test/rubygems/test_gem_commands_unpack_command.rb +4 -6
  85. data/test/rubygems/test_gem_commands_update_command.rb +22 -52
  86. data/test/rubygems/test_gem_commands_which_command.rb +1 -0
  87. data/test/rubygems/test_gem_config_file.rb +1 -1
  88. data/test/rubygems/test_gem_dependency.rb +7 -3
  89. data/test/rubygems/test_gem_dependency_installer.rb +5 -5
  90. data/test/rubygems/test_gem_doctor.rb +1 -1
  91. data/test/rubygems/test_gem_ext_builder.rb +2 -0
  92. data/test/rubygems/test_gem_ext_configure_builder.rb +8 -4
  93. data/test/rubygems/test_gem_ext_ext_conf_builder.rb +25 -21
  94. data/test/rubygems/test_gem_indexer.rb +4 -4
  95. data/test/rubygems/test_gem_install_update_options.rb +2 -2
  96. data/test/rubygems/test_gem_installer.rb +32 -26
  97. data/test/rubygems/test_gem_package.rb +46 -1
  98. data/test/rubygems/test_gem_package_tar_reader_entry.rb +8 -1
  99. data/test/rubygems/test_gem_package_tar_writer.rb +10 -1
  100. data/test/rubygems/test_gem_package_task.rb +5 -2
  101. data/test/rubygems/test_gem_platform.rb +11 -0
  102. data/test/rubygems/test_gem_remote_fetcher.rb +64 -3
  103. data/test/rubygems/test_gem_request.rb +1 -1
  104. data/test/rubygems/test_gem_request_connection_pools.rb +10 -1
  105. data/test/rubygems/test_gem_request_set.rb +5 -8
  106. data/test/rubygems/test_gem_request_set_lockfile.rb +2 -4
  107. data/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb +1 -1
  108. data/test/rubygems/test_gem_resolver.rb +12 -31
  109. data/test/rubygems/test_gem_resolver_git_specification.rb +1 -0
  110. data/test/rubygems/test_gem_resolver_installer_set.rb +7 -11
  111. data/test/rubygems/test_gem_resolver_lock_specification.rb +3 -2
  112. data/test/rubygems/test_gem_security_trust_dir.rb +2 -0
  113. data/test/rubygems/test_gem_server.rb +4 -0
  114. data/test/rubygems/test_gem_specification.rb +344 -61
  115. data/test/rubygems/test_gem_stream_ui.rb +6 -6
  116. data/test/rubygems/test_gem_stub_specification.rb +21 -6
  117. data/test/rubygems/test_gem_text.rb +2 -0
  118. data/test/rubygems/test_gem_uninstaller.rb +2 -1
  119. data/test/rubygems/test_gem_util.rb +8 -0
  120. data/test/rubygems/test_require.rb +156 -125
  121. data/util/generate_spdx_license_list.rb +21 -0
  122. data/util/update_bundled_ca_certificates.rb +2 -1
  123. metadata +42 -6
  124. metadata.gz.sig +0 -0
  125. data/lib/rubygems/util/stringio.rb +0 -34
@@ -0,0 +1,43 @@
1
+ require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph'
2
+
3
+ module Gem::Resolver::Molinillo
4
+ # This class encapsulates a dependency resolver.
5
+ # The resolver is responsible for determining which set of dependencies to
6
+ # activate, with feedback from the the {#specification_provider}
7
+ #
8
+ #
9
+ class Resolver
10
+ require 'rubygems/resolver/molinillo/lib/molinillo/resolution'
11
+
12
+ # @return [SpecificationProvider] the specification provider used
13
+ # in the resolution process
14
+ attr_reader :specification_provider
15
+
16
+ # @return [UI] the UI module used to communicate back to the user
17
+ # during the resolution process
18
+ attr_reader :resolver_ui
19
+
20
+ # @param [SpecificationProvider] specification_provider
21
+ # see {#specification_provider}
22
+ # @param [UI] resolver_ui
23
+ # see {#resolver_ui}
24
+ def initialize(specification_provider, resolver_ui)
25
+ @specification_provider = specification_provider
26
+ @resolver_ui = resolver_ui
27
+ end
28
+
29
+ # Resolves the requested dependencies into a {DependencyGraph},
30
+ # locking to the base dependency graph (if specified)
31
+ # @param [Array] requested an array of 'requested' dependencies that the
32
+ # {#specification_provider} can understand
33
+ # @param [DependencyGraph,nil] base the base dependency graph to which
34
+ # dependencies should be 'locked'
35
+ def resolve(requested, base = DependencyGraph.new)
36
+ Resolution.new(specification_provider,
37
+ resolver_ui,
38
+ requested,
39
+ base).
40
+ resolve
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,51 @@
1
+ module Gem::Resolver::Molinillo
2
+ # A state that a {Resolution} can be in
3
+ # @attr [String] name
4
+ # @attr [Array<Object>] requirements
5
+ # @attr [DependencyGraph] activated
6
+ # @attr [Object] requirement
7
+ # @attr [Object] possibility
8
+ # @attr [Integer] depth
9
+ # @attr [Set<Object>] conflicts
10
+ ResolutionState = Struct.new(
11
+ :name,
12
+ :requirements,
13
+ :activated,
14
+ :requirement,
15
+ :possibilities,
16
+ :depth,
17
+ :conflicts
18
+ )
19
+
20
+ class ResolutionState
21
+ # Returns an empty resolution state
22
+ # @return [ResolutionState] an empty state
23
+ def self.empty
24
+ new(nil, [], DependencyGraph.new, nil, nil, 0, Set.new)
25
+ end
26
+ end
27
+
28
+ # A state that encapsulates a set of {#requirements} with an {Array} of
29
+ # possibilities
30
+ class DependencyState < ResolutionState
31
+ # Removes a possibility from `self`
32
+ # @return [PossibilityState] a state with a single possibility,
33
+ # the possibility that was removed from `self`
34
+ def pop_possibility_state
35
+ PossibilityState.new(
36
+ name,
37
+ requirements.dup,
38
+ activated.dup,
39
+ requirement,
40
+ [possibilities.pop],
41
+ depth + 1,
42
+ conflicts.dup
43
+ )
44
+ end
45
+ end
46
+
47
+ # A state that encapsulates a single possibility to fulfill the given
48
+ # {#requirement}
49
+ class PossibilityState < ResolutionState
50
+ end
51
+ end
@@ -89,7 +89,7 @@ class Gem::Resolver::Specification
89
89
 
90
90
  gem = source.download spec, destination
91
91
 
92
- installer = Gem::Installer.new gem, options
92
+ installer = Gem::Installer.at gem, options
93
93
 
94
94
  yield installer if block_given?
95
95
 
@@ -12,7 +12,8 @@ require 'rubygems/platform'
12
12
  require 'rubygems/deprecate'
13
13
  require 'rubygems/basic_specification'
14
14
  require 'rubygems/stub_specification'
15
- require 'rubygems/util/stringio'
15
+ require 'rubygems/util/list'
16
+ require 'stringio'
16
17
 
17
18
  ##
18
19
  # The Specification class contains the information for a Gem. Typically
@@ -172,6 +173,8 @@ class Gem::Specification < Gem::BasicSpecification
172
173
  @@default_value[k].nil?
173
174
  }
174
175
 
176
+ @@stubs_by_name = {}
177
+
175
178
  ######################################################################
176
179
  # :section: Required gemspec attributes
177
180
 
@@ -345,7 +348,7 @@ class Gem::Specification < Gem::BasicSpecification
345
348
  add_bindir(@executables),
346
349
  @extra_rdoc_files,
347
350
  @extensions,
348
- ].flatten.uniq.compact.sort
351
+ ].flatten.compact.uniq.sort
349
352
  end
350
353
 
351
354
  ######################################################################
@@ -383,6 +386,8 @@ class Gem::Specification < Gem::BasicSpecification
383
386
  attr_reader :description
384
387
 
385
388
  ##
389
+ # :category: Recommended gemspec attributes
390
+ #
386
391
  # A contact email address (or addresses) for this gem
387
392
  #
388
393
  # Usage:
@@ -393,11 +398,13 @@ class Gem::Specification < Gem::BasicSpecification
393
398
  attr_accessor :email
394
399
 
395
400
  ##
401
+ # :category: Recommended gemspec attributes
402
+ #
396
403
  # The URL of this gem's home page
397
404
  #
398
405
  # Usage:
399
406
  #
400
- # spec.homepage = 'http://rake.rubyforge.org'
407
+ # spec.homepage = 'https://github.com/ruby/rake'
401
408
 
402
409
  attr_accessor :homepage
403
410
 
@@ -556,7 +563,7 @@ class Gem::Specification < Gem::BasicSpecification
556
563
  # Ideally you should pick one that is OSI (Open Source Initiative)
557
564
  # http://opensource.org/licenses/alphabetical approved.
558
565
  #
559
- # The most commonly used OSI approved licenses are BSD-3-Clause and MIT.
566
+ # The most commonly used OSI approved licenses are MIT and Apache-2.0.
560
567
  # GitHub also provides a license picker at http://choosealicense.com/.
561
568
  #
562
569
  # You should specify a license for your gem so that people know how they are
@@ -585,7 +592,7 @@ class Gem::Specification < Gem::BasicSpecification
585
592
  # See #license= for more discussion
586
593
  #
587
594
  # Usage:
588
- # spec.licenses = ['MIT', 'GPL-2']
595
+ # spec.licenses = ['MIT', 'GPL-2.0']
589
596
 
590
597
  def licenses= licenses
591
598
  @licenses = Array licenses
@@ -612,6 +619,10 @@ class Gem::Specification < Gem::BasicSpecification
612
619
  # ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin12.4.0]
613
620
  # #<Gem::Version "2.0.0.247">
614
621
  #
622
+ # Because patch-level is taken into account, be very careful specifying using
623
+ # `<=`: `<= 2.2.2` will not match any patch-level of 2.2.2 after the `p0`
624
+ # release. It is much safer to specify `< 2.2.3` instead
625
+ #
615
626
  # Usage:
616
627
  #
617
628
  # # This gem will work with 1.8.6 or greater...
@@ -619,6 +630,9 @@ class Gem::Specification < Gem::BasicSpecification
619
630
  #
620
631
  # # Only with ruby 2.0.x
621
632
  # spec.required_ruby_version = '~> 2.0'
633
+ #
634
+ # # Only with ruby between 2.2.0 and 2.2.2
635
+ # spec.required_ruby_version = ['>= 2.2.0', '< 2.2.3']
622
636
 
623
637
  def required_ruby_version= req
624
638
  @required_ruby_version = Gem::Requirement.create req
@@ -725,12 +739,57 @@ class Gem::Specification < Gem::BasicSpecification
725
739
  end
726
740
  end
727
741
 
728
- def self.each_stub(dirs) # :nodoc:
729
- each_gemspec(dirs) do |path|
730
- stub = Gem::StubSpecification.new(path)
731
- yield stub if stub.valid?
742
+ def self.gemspec_stubs_in dir, pattern
743
+ Dir[File.join(dir, pattern)].map { |path|
744
+ if dir == default_specifications_dir
745
+ Gem::StubSpecification.default_gemspec_stub(path)
746
+ else
747
+ Gem::StubSpecification.gemspec_stub(path)
748
+ end
749
+ }.select(&:valid?)
750
+ end
751
+ private_class_method :gemspec_stubs_in
752
+
753
+ if [].respond_to? :flat_map
754
+ def self.map_stubs(dirs, pattern) # :nodoc:
755
+ dirs.flat_map { |dir| gemspec_stubs_in(dir, pattern) }
756
+ end
757
+ else # FIXME: remove when 1.8 is dropped
758
+ def self.map_stubs(dirs, pattern) # :nodoc:
759
+ dirs.map { |dir| gemspec_stubs_in(dir, pattern) }.flatten 1
732
760
  end
733
761
  end
762
+ private_class_method :map_stubs
763
+
764
+ uniq_takes_a_block = false
765
+ [1,2].uniq { uniq_takes_a_block = true }
766
+
767
+ if uniq_takes_a_block
768
+ def self.uniq_by(list, &block) # :nodoc:
769
+ list.uniq(&block)
770
+ end
771
+ else # FIXME: remove when 1.8 is dropped
772
+ def self.uniq_by(list) # :nodoc:
773
+ values = {}
774
+ list.each { |item|
775
+ value = yield item
776
+ values[value] ||= item
777
+ }
778
+ values.values
779
+ end
780
+ end
781
+ private_class_method :uniq_by
782
+
783
+ if [].respond_to? :sort_by!
784
+ def self.sort_by! list, &block
785
+ list.sort_by!(&block)
786
+ end
787
+ else # FIXME: remove when 1.8 is dropped
788
+ def self.sort_by! list, &block
789
+ list.replace list.sort_by(&block)
790
+ end
791
+ end
792
+ private_class_method :sort_by!
734
793
 
735
794
  def self.each_spec(dirs) # :nodoc:
736
795
  each_gemspec(dirs) do |path|
@@ -744,17 +803,33 @@ class Gem::Specification < Gem::BasicSpecification
744
803
 
745
804
  def self.stubs
746
805
  @@stubs ||= begin
747
- stubs = {}
748
- each_stub([default_specifications_dir] + dirs) do |stub|
749
- stubs[stub.full_name] ||= stub
750
- end
806
+ stubs = map_stubs([default_specifications_dir] + dirs, "*.gemspec")
807
+ stubs = uniq_by(stubs) { |stub| stub.full_name }
751
808
 
752
- stubs = stubs.values
753
809
  _resort!(stubs)
810
+ @@stubs_by_name = stubs.group_by(&:name)
754
811
  stubs
755
812
  end
756
813
  end
757
814
 
815
+ EMPTY = [].freeze # :nodoc:
816
+
817
+ ##
818
+ # Returns a Gem::StubSpecification for installed gem named +name+
819
+
820
+ def self.stubs_for name
821
+ if @@stubs || @@stubs_by_name[name]
822
+ @@stubs_by_name[name] || []
823
+ else
824
+ stubs = map_stubs([default_specifications_dir] + dirs, "#{name}-*.gemspec")
825
+ stubs = uniq_by(stubs) { |stub| stub.full_name }.group_by(&:name)
826
+ stubs.each_value { |v| sort_by!(v) { |i| i.version } }
827
+
828
+ @@stubs_by_name.merge! stubs
829
+ @@stubs_by_name[name] ||= EMPTY
830
+ end
831
+ end
832
+
758
833
  def self._resort!(specs) # :nodoc:
759
834
  specs.sort! { |a, b|
760
835
  names = a.name <=> b.name
@@ -779,6 +854,7 @@ class Gem::Specification < Gem::BasicSpecification
779
854
  # properly sorted.
780
855
 
781
856
  def self.add_spec spec
857
+ warn "Gem::Specification.add_spec is deprecated and will be removed in Rubygems 3.0" unless Gem::Deprecate.skip
782
858
  # TODO: find all extraneous adds
783
859
  # puts
784
860
  # p :add_spec => [spec.full_name, caller.reject { |s| s =~ /minitest/ }]
@@ -793,6 +869,8 @@ class Gem::Specification < Gem::BasicSpecification
793
869
 
794
870
  _all << spec
795
871
  stubs << spec
872
+ (@@stubs_by_name[spec.name] ||= []) << spec
873
+ sort_by!(@@stubs_by_name[spec.name]) { |s| s.version }
796
874
  _resort!(_all)
797
875
  _resort!(stubs)
798
876
  end
@@ -801,14 +879,18 @@ class Gem::Specification < Gem::BasicSpecification
801
879
  # Adds multiple specs to the known specifications.
802
880
 
803
881
  def self.add_specs *specs
882
+ warn "Gem::Specification.add_specs is deprecated and will be removed in Rubygems 3.0" unless Gem::Deprecate.skip
883
+
804
884
  raise "nil spec!" if specs.any?(&:nil?) # TODO: remove once we're happy
805
885
 
806
886
  # TODO: this is much more efficient, but we need the extra checks for now
807
887
  # _all.concat specs
808
888
  # _resort!
809
889
 
810
- specs.each do |spec| # TODO: slow
811
- add_spec spec
890
+ Gem::Deprecate.skip_during do
891
+ specs.each do |spec| # TODO: slow
892
+ add_spec spec
893
+ end
812
894
  end
813
895
  end
814
896
 
@@ -835,6 +917,7 @@ class Gem::Specification < Gem::BasicSpecification
835
917
  # -- wilsonb
836
918
 
837
919
  def self.all= specs
920
+ @@stubs_by_name = specs.group_by(&:name)
838
921
  @@all = @@stubs = specs
839
922
  end
840
923
 
@@ -923,9 +1006,10 @@ class Gem::Specification < Gem::BasicSpecification
923
1006
  # Return the best specification that contains the file matching +path+.
924
1007
 
925
1008
  def self.find_by_path path
926
- self.find { |spec|
927
- spec.contains_requirable_file? path
1009
+ stub = stubs.find { |spec|
1010
+ spec.contains_requirable_file? path if spec
928
1011
  }
1012
+ stub && stub.to_spec
929
1013
  end
930
1014
 
931
1015
  ##
@@ -934,7 +1018,7 @@ class Gem::Specification < Gem::BasicSpecification
934
1018
 
935
1019
  def self.find_inactive_by_path path
936
1020
  stub = stubs.find { |s|
937
- s.contains_requirable_file? path unless s.activated?
1021
+ s.contains_requirable_file? path unless s.nil? || s.activated?
938
1022
  }
939
1023
  stub && stub.to_spec
940
1024
  end
@@ -946,7 +1030,7 @@ class Gem::Specification < Gem::BasicSpecification
946
1030
  # TODO: do we need these?? Kill it
947
1031
  specs = unresolved_deps.values.map { |dep| dep.to_specs }.flatten
948
1032
 
949
- specs.find_all { |spec| spec.contains_requirable_file? path }
1033
+ specs.find_all { |spec| spec.contains_requirable_file? path if spec }
950
1034
  end
951
1035
 
952
1036
  ##
@@ -957,15 +1041,13 @@ class Gem::Specification < Gem::BasicSpecification
957
1041
  specs = unresolved_deps.values.map { |dep| dep.to_specs }.flatten
958
1042
 
959
1043
  specs.reverse_each do |spec|
960
- trails = []
961
1044
  spec.traverse do |from_spec, dep, to_spec, trail|
962
- next unless to_spec.conflicts.empty?
963
- trails << trail if to_spec.contains_requirable_file? path
1045
+ if to_spec.has_conflicts? || to_spec.conficts_when_loaded_with?(trail)
1046
+ :next
1047
+ else
1048
+ return trail.reverse if to_spec.contains_requirable_file? path
1049
+ end
964
1050
  end
965
-
966
- next if trails.empty?
967
-
968
- return trails.map(&:reverse).sort.first.reverse
969
1051
  end
970
1052
 
971
1053
  []
@@ -1004,10 +1086,14 @@ class Gem::Specification < Gem::BasicSpecification
1004
1086
  # +prerelease+ is true.
1005
1087
 
1006
1088
  def self.latest_specs prerelease = false
1089
+ _latest_specs Gem::Specification._all, prerelease
1090
+ end
1091
+
1092
+ def self._latest_specs specs, prerelease = false # :nodoc:
1007
1093
  result = Hash.new { |h,k| h[k] = {} }
1008
1094
  native = {}
1009
1095
 
1010
- Gem::Specification.reverse_each do |spec|
1096
+ specs.reverse_each do |spec|
1011
1097
  next if spec.version.prerelease? unless prerelease
1012
1098
 
1013
1099
  native[spec.name] = spec.version if spec.platform == Gem::Platform::RUBY
@@ -1025,12 +1111,13 @@ class Gem::Specification < Gem::BasicSpecification
1025
1111
 
1026
1112
  def self.load file
1027
1113
  return unless file
1028
- file = file.dup.untaint
1029
- return unless File.file?(file)
1030
1114
 
1031
1115
  _spec = LOAD_CACHE[file]
1032
1116
  return _spec if _spec
1033
1117
 
1118
+ file = file.dup.untaint
1119
+ return unless File.file?(file)
1120
+
1034
1121
  code = if defined? Encoding
1035
1122
  File.read file, :mode => 'r:UTF-8:-'
1036
1123
  else
@@ -1122,8 +1209,11 @@ class Gem::Specification < Gem::BasicSpecification
1122
1209
  # Removes +spec+ from the known specs.
1123
1210
 
1124
1211
  def self.remove_spec spec
1212
+ warn "Gem::Specification.remove_spec is deprecated and will be removed in Rubygems 3.0" unless Gem::Deprecate.skip
1125
1213
  _all.delete spec
1126
1214
  stubs.delete_if { |s| s.full_name == spec.full_name }
1215
+ (@@stubs_by_name[spec.name] || []).delete_if { |s| s.full_name == spec.full_name }
1216
+ reset
1127
1217
  end
1128
1218
 
1129
1219
  ##
@@ -1149,6 +1239,7 @@ class Gem::Specification < Gem::BasicSpecification
1149
1239
  Gem.pre_reset_hooks.each { |hook| hook.call }
1150
1240
  @@all = nil
1151
1241
  @@stubs = nil
1242
+ @@stubs_by_name = {}
1152
1243
  _clear_load_cache
1153
1244
  unresolved = unresolved_deps
1154
1245
  unless unresolved.empty? then
@@ -1321,6 +1412,50 @@ class Gem::Specification < Gem::BasicSpecification
1321
1412
  unresolved.delete self.name
1322
1413
  end
1323
1414
 
1415
+ ##
1416
+ # Abbreviate the spec for downloading. Abbreviated specs are only used for
1417
+ # searching, downloading and related activities and do not need deployment
1418
+ # specific information (e.g. list of files). So we abbreviate the spec,
1419
+ # making it much smaller for quicker downloads.
1420
+
1421
+ def abbreviate
1422
+ self.files = []
1423
+ self.test_files = []
1424
+ self.rdoc_options = []
1425
+ self.extra_rdoc_files = []
1426
+ self.cert_chain = []
1427
+ end
1428
+
1429
+ ##
1430
+ # Sanitize the descriptive fields in the spec. Sometimes non-ASCII
1431
+ # characters will garble the site index. Non-ASCII characters will
1432
+ # be replaced by their XML entity equivalent.
1433
+
1434
+ def sanitize
1435
+ self.summary = sanitize_string(summary)
1436
+ self.description = sanitize_string(description)
1437
+ self.post_install_message = sanitize_string(post_install_message)
1438
+ self.authors = authors.collect { |a| sanitize_string(a) }
1439
+ end
1440
+
1441
+ ##
1442
+ # Sanitize a single string.
1443
+
1444
+ def sanitize_string(string)
1445
+ return string unless string
1446
+
1447
+ # HACK the #to_s is in here because RSpec has an Array of Arrays of
1448
+ # Strings for authors. Need a way to disallow bad values on gemspec
1449
+ # generation. (Probably won't happen.)
1450
+ string = string.to_s
1451
+
1452
+ begin
1453
+ Builder::XChar.encode string
1454
+ rescue NameError, NoMethodError
1455
+ string.to_xs
1456
+ end
1457
+ end
1458
+
1324
1459
  ##
1325
1460
  # Returns an array with bindir attached to each executable in the
1326
1461
  # +executables+ list
@@ -1515,6 +1650,30 @@ class Gem::Specification < Gem::BasicSpecification
1515
1650
  conflicts
1516
1651
  end
1517
1652
 
1653
+ ##
1654
+ # return true if there will be conflict when spec if loaded together with the list of specs.
1655
+
1656
+ def conficts_when_loaded_with?(list_of_specs) # :nodoc:
1657
+ result = list_of_specs.any? { |spec|
1658
+ spec.dependencies.any? { |dep| dep.runtime? && (dep.name == name) && !satisfies_requirement?(dep) }
1659
+ }
1660
+ result
1661
+ end
1662
+
1663
+ ##
1664
+ # Return true if there are possible conflicts against the currently loaded specs.
1665
+
1666
+ def has_conflicts?
1667
+ self.dependencies.any? { |dep|
1668
+ if dep.runtime? then
1669
+ spec = Gem.loaded_specs[dep.name]
1670
+ spec and not spec.satisfies_requirement? dep
1671
+ else
1672
+ false
1673
+ end
1674
+ }
1675
+ end
1676
+
1518
1677
  ##
1519
1678
  # The date this gem was created. Lazily defaults to the current UTC date.
1520
1679
  #
@@ -1835,9 +1994,10 @@ class Gem::Specification < Gem::BasicSpecification
1835
1994
  # +version+.
1836
1995
 
1837
1996
  def initialize name = nil, version = nil
1997
+ super()
1838
1998
  @loaded = false
1839
1999
  @activated = false
1840
- self.loaded_from = nil
2000
+ @loaded_from = nil
1841
2001
  @original_platform = nil
1842
2002
  @installed_by_version = nil
1843
2003
 
@@ -1903,20 +2063,6 @@ class Gem::Specification < Gem::BasicSpecification
1903
2063
  end
1904
2064
  end
1905
2065
 
1906
- ##
1907
- # Returns a string usable in Dir.glob to match all requirable paths
1908
- # for this spec.
1909
-
1910
- def lib_dirs_glob
1911
- dirs = if self.require_paths.size > 1 then
1912
- "{#{self.require_paths.join(',')}}"
1913
- else
1914
- self.require_paths.first
1915
- end
1916
-
1917
- "#{self.full_gem_path}/#{dirs}"
1918
- end
1919
-
1920
2066
  ##
1921
2067
  # Files in the Gem under one of the require_paths
1922
2068
 
@@ -1944,9 +2090,8 @@ class Gem::Specification < Gem::BasicSpecification
1944
2090
  @licenses ||= []
1945
2091
  end
1946
2092
 
1947
- def loaded_from= path # :nodoc:
2093
+ def internal_init # :nodoc:
1948
2094
  super
1949
-
1950
2095
  @bin_dir = nil
1951
2096
  @cache_dir = nil
1952
2097
  @cache_file = nil
@@ -1963,16 +2108,6 @@ class Gem::Specification < Gem::BasicSpecification
1963
2108
  @rubygems_version = Gem::VERSION
1964
2109
  end
1965
2110
 
1966
- ##
1967
- # Return all files in this gem that match for +glob+.
1968
-
1969
- def matches_for_glob glob # TODO: rename?
1970
- # TODO: do we need these?? Kill it
1971
- glob = File.join(self.lib_dirs_glob, glob)
1972
-
1973
- Dir[glob].map { |f| f.untaint } # FIX our tests are broken, run w/ SAFE=1
1974
- end
1975
-
1976
2111
  ##
1977
2112
  # Warn about unknown attributes while loading a spec.
1978
2113
 
@@ -2106,10 +2241,8 @@ class Gem::Specification < Gem::BasicSpecification
2106
2241
  # Check the spec for possible conflicts and freak out if there are any.
2107
2242
 
2108
2243
  def raise_if_conflicts # :nodoc:
2109
- conf = self.conflicts
2110
-
2111
- unless conf.empty? then
2112
- raise Gem::ConflictError.new self, conf
2244
+ if has_conflicts? then
2245
+ raise Gem::ConflictError.new self, conflicts
2113
2246
  end
2114
2247
  end
2115
2248
 
@@ -2186,7 +2319,7 @@ class Gem::Specification < Gem::BasicSpecification
2186
2319
  # List of dependencies that will automatically be activated at runtime.
2187
2320
 
2188
2321
  def runtime_dependencies
2189
- dependencies.select { |d| d.type == :runtime }
2322
+ dependencies.select(&:runtime?)
2190
2323
  end
2191
2324
 
2192
2325
  ##
@@ -2413,7 +2546,7 @@ class Gem::Specification < Gem::BasicSpecification
2413
2546
  builder << self
2414
2547
  ast = builder.tree
2415
2548
 
2416
- io = Gem::StringSink.new
2549
+ io = StringIO.new
2417
2550
  io.set_encoding Encoding::UTF_8 if Object.const_defined? :Encoding
2418
2551
 
2419
2552
  Psych::Visitors::Emitter.new(io).accept(ast)
@@ -2432,14 +2565,28 @@ class Gem::Specification < Gem::BasicSpecification
2432
2565
  # Recursively walk dependencies of this spec, executing the +block+ for each
2433
2566
  # hop.
2434
2567
 
2435
- def traverse trail = [], &block
2436
- trail = trail + [self]
2437
- runtime_dependencies.each do |dep|
2438
- dep.to_specs.each do |dep_spec|
2439
- block[self, dep, dep_spec, trail + [dep_spec]]
2440
- dep_spec.traverse(trail, &block) unless
2441
- trail.map(&:name).include? dep_spec.name
2568
+ def traverse trail = [], visited = {}, &block
2569
+ trail.push(self)
2570
+ begin
2571
+ dependencies.each do |dep|
2572
+ dep.to_specs.reverse_each do |dep_spec|
2573
+ next if visited.has_key?(dep_spec)
2574
+ visited[dep_spec] = true
2575
+ trail.push(dep_spec)
2576
+ begin
2577
+ result = block[self, dep, dep_spec, trail]
2578
+ ensure
2579
+ trail.pop
2580
+ end
2581
+ unless result == :next
2582
+ spec_name = dep_spec.name
2583
+ dep_spec.traverse(trail, visited, &block) unless
2584
+ trail.any? { |s| s.name == spec_name }
2585
+ end
2586
+ end
2442
2587
  end
2588
+ ensure
2589
+ trail.pop
2443
2590
  end
2444
2591
  end
2445
2592
 
@@ -2487,13 +2634,13 @@ class Gem::Specification < Gem::BasicSpecification
2487
2634
  'specification must have at least one require_path'
2488
2635
  end
2489
2636
 
2490
- @files.delete_if { |x| File.directory?(x) }
2491
- @test_files.delete_if { |x| File.directory?(x) }
2637
+ @files.delete_if { |x| File.directory?(x) && !File.symlink?(x) }
2638
+ @test_files.delete_if { |x| File.directory?(x) && !File.symlink?(x) }
2492
2639
  @executables.delete_if { |x| File.directory?(File.join(@bindir, x)) }
2493
- @extra_rdoc_files.delete_if { |x| File.directory?(x) }
2494
- @extensions.delete_if { |x| File.directory?(x) }
2640
+ @extra_rdoc_files.delete_if { |x| File.directory?(x) && !File.symlink?(x) }
2641
+ @extensions.delete_if { |x| File.directory?(x) && !File.symlink?(x) }
2495
2642
 
2496
- non_files = files.reject { |x| File.file?(x) }
2643
+ non_files = files.reject { |x| File.file?(x) || File.symlink?(x) }
2497
2644
 
2498
2645
  unless not packaging or non_files.empty? then
2499
2646
  raise Gem::InvalidSpecificationException,
@@ -2572,11 +2719,18 @@ class Gem::Specification < Gem::BasicSpecification
2572
2719
  raise Gem::InvalidSpecificationException,
2573
2720
  "each license must be 64 characters or less"
2574
2721
  end
2722
+
2723
+ if !Gem::Licenses::IDENTIFIERS.include?(license) && !license.eql?(Gem::Licenses::NONSTANDARD)
2724
+ warning <<-warning
2725
+ WARNING: license value '#{license}' is invalid. Use a license identifier from
2726
+ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard license.
2727
+ warning
2728
+ end
2575
2729
  }
2576
2730
 
2577
2731
  warning <<-warning if licenses.empty?
2578
- licenses is empty, but is recommended. Use a license abbreviation from:
2579
- http://opensource.org/licenses/alphabetical
2732
+ licenses is empty, but is recommended. Use a license identifier from
2733
+ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard license.
2580
2734
  warning
2581
2735
 
2582
2736
  validate_permissions
@@ -2609,7 +2763,7 @@ http://opensource.org/licenses/alphabetical
2609
2763
 
2610
2764
  # Warnings
2611
2765
 
2612
- %w[author description email homepage summary].each do |attribute|
2766
+ %w[author email homepage summary].each do |attribute|
2613
2767
  value = self.send attribute
2614
2768
  warning "no #{attribute} specified" if value.nil? or value.empty?
2615
2769
  end
@@ -2628,6 +2782,11 @@ http://opensource.org/licenses/alphabetical
2628
2782
  warning "#{executable_path} is missing #! line" unless shebang
2629
2783
  end
2630
2784
 
2785
+ files.each do |file|
2786
+ next unless File.symlink?(file)
2787
+ warning "#{file} is a symlink, which is not supported on all platforms"
2788
+ end
2789
+
2631
2790
  validate_dependencies
2632
2791
 
2633
2792
  true
@@ -2643,23 +2802,26 @@ http://opensource.org/licenses/alphabetical
2643
2802
  # versioning.
2644
2803
 
2645
2804
  def validate_dependencies # :nodoc:
2646
- seen = {}
2805
+ # NOTE: see REFACTOR note in Gem::Dependency about types - this might be brittle
2806
+ seen = Gem::Dependency::TYPES.inject({}) { |types, type| types.merge({ type => {}}) }
2647
2807
 
2808
+ error_messages = []
2809
+ warning_messages = []
2648
2810
  dependencies.each do |dep|
2649
- if prev = seen[dep.name] then
2650
- raise Gem::InvalidSpecificationException, <<-MESSAGE
2811
+ if prev = seen[dep.type][dep.name] then
2812
+ error_messages << <<-MESSAGE
2651
2813
  duplicate dependency on #{dep}, (#{prev.requirement}) use:
2652
- add_runtime_dependency '#{dep.name}', '#{dep.requirement}', '#{prev.requirement}'
2814
+ add_#{dep.type}_dependency '#{dep.name}', '#{dep.requirement}', '#{prev.requirement}'
2653
2815
  MESSAGE
2654
2816
  end
2655
2817
 
2656
- seen[dep.name] = dep
2818
+ seen[dep.type][dep.name] = dep
2657
2819
 
2658
2820
  prerelease_dep = dep.requirements_list.any? do |req|
2659
2821
  Gem::Requirement.new(req).prerelease?
2660
2822
  end
2661
2823
 
2662
- warning "prerelease dependency on #{dep} is not recommended" if
2824
+ warning_messages << "prerelease dependency on #{dep} is not recommended" if
2663
2825
  prerelease_dep
2664
2826
 
2665
2827
  overly_strict = dep.requirement.requirements.length == 1 &&
@@ -2675,7 +2837,7 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
2675
2837
 
2676
2838
  base = dep_version.segments.first 2
2677
2839
 
2678
- warning <<-WARNING
2840
+ warning_messages << <<-WARNING
2679
2841
  pessimistic dependency on #{dep} may be overly strict
2680
2842
  if #{dep.name} is semantically versioned, use:
2681
2843
  add_#{dep.type}_dependency '#{dep.name}', '~> #{base.join '.'}', '>= #{dep_version}'
@@ -2697,13 +2859,19 @@ pessimistic dependency on #{dep} may be overly strict
2697
2859
  ", '>= #{dep_version}'"
2698
2860
  end
2699
2861
 
2700
- warning <<-WARNING
2862
+ warning_messages << <<-WARNING
2701
2863
  open-ended dependency on #{dep} is not recommended
2702
2864
  if #{dep.name} is semantically versioned, use:
2703
2865
  add_#{dep.type}_dependency '#{dep.name}', '~> #{base.join '.'}'#{bugfix}
2704
2866
  WARNING
2705
2867
  end
2706
2868
  end
2869
+ if error_messages.any?
2870
+ raise Gem::InvalidSpecificationException, error_messages.join
2871
+ end
2872
+ if warning_messages.any?
2873
+ warning_messages.each { |warning_message| warning warning_message }
2874
+ end
2707
2875
  end
2708
2876
 
2709
2877
  ##
@@ -2713,12 +2881,14 @@ open-ended dependency on #{dep} is not recommended
2713
2881
  return if Gem.win_platform?
2714
2882
 
2715
2883
  files.each do |file|
2884
+ next unless File.file?(file)
2716
2885
  next if File.stat(file).mode & 0444 == 0444
2717
2886
  warning "#{file} is not world-readable"
2718
2887
  end
2719
2888
 
2720
2889
  executables.each do |name|
2721
2890
  exec = File.join @bindir, name
2891
+ next unless File.file?(exec)
2722
2892
  next if File.stat(exec).executable?
2723
2893
  warning "#{exec} is not executable"
2724
2894
  end