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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CODE_OF_CONDUCT.md +40 -0
- data/CVE-2015-3900.txt +40 -0
- data/History.txt +173 -2
- data/Manifest.txt +14 -1
- data/Rakefile +36 -1
- data/lib/rubygems.rb +32 -14
- data/lib/rubygems/basic_specification.rb +31 -9
- data/lib/rubygems/commands/dependency_command.rb +25 -15
- data/lib/rubygems/commands/environment_command.rb +2 -0
- data/lib/rubygems/commands/help_command.rb +0 -10
- data/lib/rubygems/commands/install_command.rb +1 -1
- data/lib/rubygems/commands/list_command.rb +1 -1
- data/lib/rubygems/commands/pristine_command.rb +11 -1
- data/lib/rubygems/commands/query_command.rb +1 -1
- data/lib/rubygems/commands/sources_command.rb +1 -1
- data/lib/rubygems/commands/update_command.rb +2 -2
- data/lib/rubygems/config_file.rb +4 -4
- data/lib/rubygems/core_ext/kernel_require.rb +2 -2
- data/lib/rubygems/dependency.rb +9 -6
- data/lib/rubygems/dependency_list.rb +3 -0
- data/lib/rubygems/ext/builder.rb +2 -0
- data/lib/rubygems/ext/ext_conf_builder.rb +6 -1
- data/lib/rubygems/indexer.rb +26 -91
- data/lib/rubygems/installer.rb +58 -26
- data/lib/rubygems/installer_test_case.rb +2 -2
- data/lib/rubygems/package.rb +18 -6
- data/lib/rubygems/package/old.rb +2 -2
- data/lib/rubygems/package/tar_reader/entry.rb +7 -1
- data/lib/rubygems/package/tar_test_case.rb +12 -3
- data/lib/rubygems/package/tar_writer.rb +19 -1
- data/lib/rubygems/platform.rb +3 -2
- data/lib/rubygems/rdoc.rb +1 -2
- data/lib/rubygems/remote_fetcher.rb +25 -6
- data/lib/rubygems/request/connection_pools.rb +8 -4
- data/lib/rubygems/request_set.rb +3 -4
- data/lib/rubygems/request_set/gem_dependency_api.rb +2 -2
- data/lib/rubygems/request_set/lockfile.rb +1 -1
- data/lib/rubygems/request_set/lockfile/parser.rb +54 -43
- data/lib/rubygems/request_set/lockfile/tokenizer.rb +16 -13
- data/lib/rubygems/resolver.rb +47 -242
- data/lib/rubygems/resolver/activation_request.rb +2 -1
- data/lib/rubygems/resolver/conflict.rb +0 -1
- data/lib/rubygems/resolver/dependency_request.rb +4 -1
- data/lib/rubygems/resolver/git_specification.rb +1 -2
- data/lib/rubygems/resolver/molinillo.rb +1 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo.rb +5 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb +266 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb +69 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb +3 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb +99 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb +63 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb +430 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb +43 -0
- data/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb +51 -0
- data/lib/rubygems/resolver/specification.rb +1 -1
- data/lib/rubygems/specification.rb +256 -86
- data/lib/rubygems/stub_specification.rb +37 -29
- data/lib/rubygems/test_case.rb +65 -28
- data/lib/rubygems/test_utilities.rb +18 -18
- data/lib/rubygems/text.rb +0 -2
- data/lib/rubygems/uninstaller.rb +1 -1
- data/lib/rubygems/util.rb +4 -4
- data/lib/rubygems/util/licenses.rb +309 -0
- data/lib/rubygems/util/list.rb +9 -21
- data/lib/rubygems/version.rb +24 -14
- data/test/rubygems/simple_gem.rb +1 -1
- data/test/rubygems/test_config.rb +10 -1
- data/test/rubygems/test_gem.rb +58 -11
- data/test/rubygems/test_gem_available_set.rb +2 -1
- data/test/rubygems/test_gem_commands_cleanup_command.rb +6 -5
- data/test/rubygems/test_gem_commands_dependency_command.rb +9 -1
- data/test/rubygems/test_gem_commands_install_command.rb +17 -28
- data/test/rubygems/test_gem_commands_mirror.rb +0 -13
- data/test/rubygems/test_gem_commands_outdated_command.rb +2 -3
- data/test/rubygems/test_gem_commands_pristine_command.rb +33 -5
- data/test/rubygems/test_gem_commands_query_command.rb +123 -158
- data/test/rubygems/test_gem_commands_server_command.rb +2 -2
- data/test/rubygems/test_gem_commands_specification_command.rb +4 -4
- data/test/rubygems/test_gem_commands_stale_command.rb +2 -0
- data/test/rubygems/test_gem_commands_uninstall_command.rb +5 -4
- data/test/rubygems/test_gem_commands_unpack_command.rb +4 -6
- data/test/rubygems/test_gem_commands_update_command.rb +22 -52
- data/test/rubygems/test_gem_commands_which_command.rb +1 -0
- data/test/rubygems/test_gem_config_file.rb +1 -1
- data/test/rubygems/test_gem_dependency.rb +7 -3
- data/test/rubygems/test_gem_dependency_installer.rb +5 -5
- data/test/rubygems/test_gem_doctor.rb +1 -1
- data/test/rubygems/test_gem_ext_builder.rb +2 -0
- data/test/rubygems/test_gem_ext_configure_builder.rb +8 -4
- data/test/rubygems/test_gem_ext_ext_conf_builder.rb +25 -21
- data/test/rubygems/test_gem_indexer.rb +4 -4
- data/test/rubygems/test_gem_install_update_options.rb +2 -2
- data/test/rubygems/test_gem_installer.rb +32 -26
- data/test/rubygems/test_gem_package.rb +46 -1
- data/test/rubygems/test_gem_package_tar_reader_entry.rb +8 -1
- data/test/rubygems/test_gem_package_tar_writer.rb +10 -1
- data/test/rubygems/test_gem_package_task.rb +5 -2
- data/test/rubygems/test_gem_platform.rb +11 -0
- data/test/rubygems/test_gem_remote_fetcher.rb +64 -3
- data/test/rubygems/test_gem_request.rb +1 -1
- data/test/rubygems/test_gem_request_connection_pools.rb +10 -1
- data/test/rubygems/test_gem_request_set.rb +5 -8
- data/test/rubygems/test_gem_request_set_lockfile.rb +2 -4
- data/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb +1 -1
- data/test/rubygems/test_gem_resolver.rb +12 -31
- data/test/rubygems/test_gem_resolver_git_specification.rb +1 -0
- data/test/rubygems/test_gem_resolver_installer_set.rb +7 -11
- data/test/rubygems/test_gem_resolver_lock_specification.rb +3 -2
- data/test/rubygems/test_gem_security_trust_dir.rb +2 -0
- data/test/rubygems/test_gem_server.rb +4 -0
- data/test/rubygems/test_gem_specification.rb +344 -61
- data/test/rubygems/test_gem_stream_ui.rb +6 -6
- data/test/rubygems/test_gem_stub_specification.rb +21 -6
- data/test/rubygems/test_gem_text.rb +2 -0
- data/test/rubygems/test_gem_uninstaller.rb +2 -1
- data/test/rubygems/test_gem_util.rb +8 -0
- data/test/rubygems/test_require.rb +156 -125
- data/util/generate_spdx_license_list.rb +21 -0
- data/util/update_bundled_ca_certificates.rb +2 -1
- metadata +42 -6
- metadata.gz.sig +0 -0
- 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
|
@@ -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/
|
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.
|
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 = '
|
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
|
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.
|
729
|
-
|
730
|
-
|
731
|
-
|
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
|
-
|
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
|
-
|
811
|
-
|
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
|
-
|
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
|
-
|
963
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
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 =
|
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
|
2437
|
-
|
2438
|
-
|
2439
|
-
|
2440
|
-
|
2441
|
-
|
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
|
2579
|
-
http://
|
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
|
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
|
-
|
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
|
-
|
2811
|
+
if prev = seen[dep.type][dep.name] then
|
2812
|
+
error_messages << <<-MESSAGE
|
2651
2813
|
duplicate dependency on #{dep}, (#{prev.requirement}) use:
|
2652
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|