rubygems-update 2.5.0 → 2.5.1

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.

@@ -1,3 +1,3 @@
1
1
  module Gem::Resolver::Molinillo
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -12,13 +12,15 @@ module Gem::Resolver::Molinillo
12
12
  # @attr [Object] locked_requirement the relevant locking requirement.
13
13
  # @attr [Array<Array<Object>>] requirement_trees the different requirement
14
14
  # trees that led to every requirement for the conflicting name.
15
+ # @attr [{String=>Object}] activated_by_name the already-activated specs.
15
16
  Conflict = Struct.new(
16
17
  :requirement,
17
18
  :requirements,
18
19
  :existing,
19
20
  :possibility,
20
21
  :locked_requirement,
21
- :requirement_trees
22
+ :requirement_trees,
23
+ :activated_by_name
22
24
  )
23
25
 
24
26
  # @return [SpecificationProvider] the provider that knows about
@@ -164,7 +166,7 @@ module Gem::Resolver::Molinillo
164
166
  # @return [DependencyState] the initial state for the resolution
165
167
  def initial_state
166
168
  graph = DependencyGraph.new.tap do |dg|
167
- original_requested.each { |r| dg.add_root_vertex(name_for(r), nil).tap { |v| v.explicit_requirements << r } }
169
+ original_requested.each { |r| dg.add_vertex(name_for(r), nil, true).tap { |v| v.explicit_requirements << r } }
168
170
  end
169
171
 
170
172
  requirements = sort_dependencies(original_requested, graph, {})
@@ -216,7 +218,7 @@ module Gem::Resolver::Molinillo
216
218
  return nil unless requirement
217
219
  seen = false
218
220
  state = states.reverse_each.find do |s|
219
- seen ||= s.requirement == requirement
221
+ seen ||= s.requirement == requirement || s.requirements.include?(requirement)
220
222
  seen && s.requirement != requirement && !s.requirements.include?(requirement)
221
223
  end
222
224
  state && state.requirement
@@ -250,21 +252,23 @@ module Gem::Resolver::Molinillo
250
252
  name_for_explicit_dependency_source => vertex.explicit_requirements,
251
253
  name_for_locking_dependency_source => Array(locked_requirement_named(name)),
252
254
  }
253
- vertex.incoming_edges.each { |edge| (requirements[edge.origin.payload] ||= []).unshift(*edge.requirements) }
255
+ vertex.incoming_edges.each { |edge| (requirements[edge.origin.payload] ||= []).unshift(edge.requirement) }
254
256
  conflicts[name] = Conflict.new(
255
257
  requirement,
256
258
  Hash[requirements.select { |_, r| !r.empty? }],
257
259
  vertex.payload,
258
260
  possibility,
259
261
  locked_requirement_named(name),
260
- requirement_trees
262
+ requirement_trees,
263
+ Hash[activated.map { |v| [v.name, v.payload] }.select(&:last)]
261
264
  )
262
265
  end
263
266
 
264
267
  # @return [Array<Array<Object>>] The different requirement
265
268
  # trees that led to every requirement for the current spec.
266
269
  def requirement_trees
267
- activated.vertex_named(name).requirements.map { |r| requirement_tree_for(r) }
270
+ vertex = activated.vertex_named(name)
271
+ vertex.requirements.map { |r| requirement_tree_for(r) }
268
272
  end
269
273
 
270
274
  # @return [Array<Object>] the list of requirements that led to
@@ -322,7 +326,7 @@ module Gem::Resolver::Molinillo
322
326
  existing_spec = existing_node.payload
323
327
  if requirement_satisfied_by?(requirement, activated, existing_spec)
324
328
  new_requirements = requirements.dup
325
- push_state_for_requirements(new_requirements)
329
+ push_state_for_requirements(new_requirements, false)
326
330
  else
327
331
  return if attempt_to_swap_possibility
328
332
  create_conflict
@@ -389,17 +393,17 @@ module Gem::Resolver::Molinillo
389
393
  def require_nested_dependencies_for(activated_spec)
390
394
  nested_dependencies = dependencies_for(activated_spec)
391
395
  debug(depth) { "Requiring nested dependencies (#{nested_dependencies.map(&:to_s).join(', ')})" }
392
- nested_dependencies.each { |d| activated.add_child_vertex name_for(d), nil, [name_for(activated_spec)], d }
396
+ nested_dependencies.each { |d| activated.add_child_vertex(name_for(d), nil, [name_for(activated_spec)], d) }
393
397
 
394
- push_state_for_requirements(requirements + nested_dependencies)
398
+ push_state_for_requirements(requirements + nested_dependencies, nested_dependencies.size > 0)
395
399
  end
396
400
 
397
401
  # Pushes a new {DependencyState} that encapsulates both existing and new
398
402
  # requirements
399
403
  # @param [Array] new_requirements
400
404
  # @return [void]
401
- def push_state_for_requirements(new_requirements, new_activated = activated.dup)
402
- new_requirements = sort_dependencies(new_requirements.uniq, new_activated, conflicts)
405
+ def push_state_for_requirements(new_requirements, requires_sort = true, new_activated = activated.dup)
406
+ new_requirements = sort_dependencies(new_requirements.uniq, new_activated, conflicts) if requires_sort
403
407
  new_requirement = new_requirements.shift
404
408
  new_name = new_requirement ? name_for(new_requirement) : ''
405
409
  possibilities = new_requirement ? search_for(new_requirement) : []
@@ -420,7 +424,7 @@ module Gem::Resolver::Molinillo
420
424
  def handle_missing_or_push_dependency_state(state)
421
425
  if state.requirement && state.possibilities.empty? && allow_missing?(state.requirement)
422
426
  state.activated.detach_vertex_named(state.name)
423
- push_state_for_requirements(state.requirements, state.activated)
427
+ push_state_for_requirements(state.requirements.dup, false, state.activated)
424
428
  else
425
429
  states.push state
426
430
  end
@@ -175,6 +175,11 @@ class Gem::Specification < Gem::BasicSpecification
175
175
 
176
176
  @@stubs_by_name = {}
177
177
 
178
+ # Sentinel object to represent "not found" stubs
179
+ NOT_FOUND = Struct.new(:to_spec, :this).new # :nodoc:
180
+ @@spec_with_requirable_file = {}
181
+ @@active_stub_with_requirable_file = {}
182
+
178
183
  ######################################################################
179
184
  # :section: Required gemspec attributes
180
185
 
@@ -740,23 +745,41 @@ class Gem::Specification < Gem::BasicSpecification
740
745
  end
741
746
 
742
747
  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?)
748
+ Dir[File.join(dir, pattern)].map { |path| yield path }.select(&:valid?)
750
749
  end
751
750
  private_class_method :gemspec_stubs_in
752
751
 
752
+ def self.default_stubs pattern
753
+ base_dir = Gem.default_dir
754
+ gems_dir = File.join base_dir, "gems"
755
+ gemspec_stubs_in(default_specifications_dir, pattern) do |path|
756
+ Gem::StubSpecification.default_gemspec_stub(path, base_dir, gems_dir)
757
+ end
758
+ end
759
+ private_class_method :default_stubs
760
+
761
+ def self.installed_stubs dirs, pattern
762
+ map_stubs(dirs, pattern) do |path, base_dir, gems_dir|
763
+ Gem::StubSpecification.gemspec_stub(path, base_dir, gems_dir)
764
+ end
765
+ end
766
+ private_class_method :installed_stubs
767
+
753
768
  if [].respond_to? :flat_map
754
769
  def self.map_stubs(dirs, pattern) # :nodoc:
755
- dirs.flat_map { |dir| gemspec_stubs_in(dir, pattern) }
770
+ dirs.flat_map { |dir|
771
+ base_dir = File.dirname dir
772
+ gems_dir = File.join base_dir, "gems"
773
+ gemspec_stubs_in(dir, pattern) { |path| yield path, base_dir, gems_dir }
774
+ }
756
775
  end
757
776
  else # FIXME: remove when 1.8 is dropped
758
777
  def self.map_stubs(dirs, pattern) # :nodoc:
759
- dirs.map { |dir| gemspec_stubs_in(dir, pattern) }.flatten 1
778
+ dirs.map { |dir|
779
+ base_dir = File.dirname dir
780
+ gems_dir = File.join base_dir, "gems"
781
+ gemspec_stubs_in(dir, pattern) { |path| yield path, base_dir, gems_dir }
782
+ }.flatten 1
760
783
  end
761
784
  end
762
785
  private_class_method :map_stubs
@@ -803,7 +826,8 @@ class Gem::Specification < Gem::BasicSpecification
803
826
 
804
827
  def self.stubs
805
828
  @@stubs ||= begin
806
- stubs = map_stubs([default_specifications_dir] + dirs, "*.gemspec")
829
+ pattern = "*.gemspec"
830
+ stubs = default_stubs(pattern).concat installed_stubs(dirs, pattern)
807
831
  stubs = uniq_by(stubs) { |stub| stub.full_name }
808
832
 
809
833
  _resort!(stubs)
@@ -818,10 +842,11 @@ class Gem::Specification < Gem::BasicSpecification
818
842
  # Returns a Gem::StubSpecification for installed gem named +name+
819
843
 
820
844
  def self.stubs_for name
821
- if @@stubs || @@stubs_by_name[name]
845
+ if @@stubs
822
846
  @@stubs_by_name[name] || []
823
847
  else
824
- stubs = map_stubs([default_specifications_dir] + dirs, "#{name}-*.gemspec")
848
+ pattern = "#{name}-*.gemspec"
849
+ stubs = default_stubs(pattern) + installed_stubs(dirs, pattern)
825
850
  stubs = uniq_by(stubs) { |stub| stub.full_name }.group_by(&:name)
826
851
  stubs.each_value { |v| sort_by!(v) { |i| i.version } }
827
852
 
@@ -1006,10 +1031,11 @@ class Gem::Specification < Gem::BasicSpecification
1006
1031
  # Return the best specification that contains the file matching +path+.
1007
1032
 
1008
1033
  def self.find_by_path path
1009
- stub = stubs.find { |spec|
1010
- spec.contains_requirable_file? path if spec
1011
- }
1012
- stub && stub.to_spec
1034
+ path = path.dup.freeze
1035
+ spec = @@spec_with_requirable_file[path] ||= (stubs.find { |s|
1036
+ s.contains_requirable_file? path
1037
+ } || NOT_FOUND)
1038
+ spec.to_spec
1013
1039
  end
1014
1040
 
1015
1041
  ##
@@ -1018,11 +1044,18 @@ class Gem::Specification < Gem::BasicSpecification
1018
1044
 
1019
1045
  def self.find_inactive_by_path path
1020
1046
  stub = stubs.find { |s|
1021
- s.contains_requirable_file? path unless s.nil? || s.activated?
1047
+ s.contains_requirable_file? path unless s.activated?
1022
1048
  }
1023
1049
  stub && stub.to_spec
1024
1050
  end
1025
1051
 
1052
+ def self.find_active_stub_by_path path
1053
+ stub = @@active_stub_with_requirable_file[path] ||= (stubs.find { |s|
1054
+ s.activated? and s.contains_requirable_file? path
1055
+ } || NOT_FOUND)
1056
+ stub.this
1057
+ end
1058
+
1026
1059
  ##
1027
1060
  # Return currently unresolved specs that contain the file matching +path+.
1028
1061
 
@@ -1030,7 +1063,7 @@ class Gem::Specification < Gem::BasicSpecification
1030
1063
  # TODO: do we need these?? Kill it
1031
1064
  specs = unresolved_deps.values.map { |dep| dep.to_specs }.flatten
1032
1065
 
1033
- specs.find_all { |spec| spec.contains_requirable_file? path if spec }
1066
+ specs.find_all { |spec| spec.contains_requirable_file? path }
1034
1067
  end
1035
1068
 
1036
1069
  ##
@@ -1240,6 +1273,8 @@ class Gem::Specification < Gem::BasicSpecification
1240
1273
  @@all = nil
1241
1274
  @@stubs = nil
1242
1275
  @@stubs_by_name = {}
1276
+ @@spec_with_requirable_file = {}
1277
+ @@active_stub_with_requirable_file = {}
1243
1278
  _clear_load_cache
1244
1279
  unresolved = unresolved_deps
1245
1280
  unless unresolved.empty? then
@@ -1924,23 +1959,10 @@ class Gem::Specification < Gem::BasicSpecification
1924
1959
  spec
1925
1960
  end
1926
1961
 
1927
- def find_full_gem_path # :nodoc:
1928
- super || File.expand_path(File.join(gems_dir, original_name))
1929
- end
1930
- private :find_full_gem_path
1931
-
1932
1962
  def full_name
1933
1963
  @full_name ||= super
1934
1964
  end
1935
1965
 
1936
- ##
1937
- # The path to the gem.build_complete file within the extension install
1938
- # directory.
1939
-
1940
- def gem_build_complete_path # :nodoc:
1941
- File.join extension_dir, 'gem.build_complete'
1942
- end
1943
-
1944
1966
  ##
1945
1967
  # Work around bundler removing my methods
1946
1968
 
@@ -1948,6 +1970,11 @@ class Gem::Specification < Gem::BasicSpecification
1948
1970
  super
1949
1971
  end
1950
1972
 
1973
+ def gems_dir
1974
+ # TODO: this logic seems terribly broken, but tests fail if just base_dir
1975
+ @gems_dir ||= File.join(loaded_from && base_dir || Gem.dir, "gems")
1976
+ end
1977
+
1951
1978
  ##
1952
1979
  # Deprecated and ignored, defaults to true.
1953
1980
  #
@@ -1995,6 +2022,8 @@ class Gem::Specification < Gem::BasicSpecification
1995
2022
 
1996
2023
  def initialize name = nil, version = nil
1997
2024
  super()
2025
+ @gems_dir = nil
2026
+ @base_dir = nil
1998
2027
  @loaded = false
1999
2028
  @activated = false
2000
2029
  @loaded_from = nil
@@ -2044,6 +2073,15 @@ class Gem::Specification < Gem::BasicSpecification
2044
2073
  end
2045
2074
  end
2046
2075
 
2076
+ def base_dir
2077
+ return Gem.dir unless loaded_from
2078
+ @base_dir ||= if default_gem? then
2079
+ File.dirname File.dirname File.dirname loaded_from
2080
+ else
2081
+ File.dirname File.dirname loaded_from
2082
+ end
2083
+ end
2084
+
2047
2085
  ##
2048
2086
  # Expire memoized instance variables that can incorrectly generate, replace
2049
2087
  # or miss files due changes in certain attributes used to compute them.
@@ -2569,6 +2607,7 @@ class Gem::Specification < Gem::BasicSpecification
2569
2607
  trail.push(self)
2570
2608
  begin
2571
2609
  dependencies.each do |dep|
2610
+ next unless dep.runtime?
2572
2611
  dep.to_specs.reverse_each do |dep_spec|
2573
2612
  next if visited.has_key?(dep_spec)
2574
2613
  visited[dep_spec] = true
@@ -2720,7 +2759,7 @@ class Gem::Specification < Gem::BasicSpecification
2720
2759
  "each license must be 64 characters or less"
2721
2760
  end
2722
2761
 
2723
- if !Gem::Licenses::IDENTIFIERS.include?(license) && !license.eql?(Gem::Licenses::NONSTANDARD)
2762
+ if !Gem::Licenses.match?(license)
2724
2763
  warning <<-warning
2725
2764
  WARNING: license value '#{license}' is invalid. Use a license identifier from
2726
2765
  http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard license.
@@ -2822,7 +2861,7 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
2822
2861
  end
2823
2862
 
2824
2863
  warning_messages << "prerelease dependency on #{dep} is not recommended" if
2825
- prerelease_dep
2864
+ prerelease_dep && !version.prerelease?
2826
2865
 
2827
2866
  overly_strict = dep.requirement.requirements.length == 1 &&
2828
2867
  dep.requirement.requirements.any? do |op, version|
@@ -2954,6 +2993,10 @@ open-ended dependency on #{dep} is not recommended
2954
2993
  alert_warning statement
2955
2994
  end
2956
2995
 
2996
+ def raw_require_paths # :nodoc:
2997
+ @require_paths
2998
+ end
2999
+
2957
3000
  extend Gem::Deprecate
2958
3001
 
2959
3002
  # TODO:
@@ -15,33 +15,65 @@ class Gem::StubSpecification < Gem::BasicSpecification
15
15
  end
16
16
 
17
17
  class StubLine # :nodoc: all
18
- attr_reader :name, :version, :platform, :require_paths
19
-
20
- def initialize(data)
21
- parts = data[PREFIX.length..-1].split(" ")
18
+ attr_reader :name, :version, :platform, :require_paths, :extensions,
19
+ :full_name
20
+
21
+ NO_EXTENSIONS = [].freeze
22
+
23
+ # These are common require paths.
24
+ REQUIRE_PATHS = { # :nodoc:
25
+ 'lib' => 'lib'.freeze,
26
+ 'test' => 'test'.freeze,
27
+ 'ext' => 'ext'.freeze,
28
+ }
29
+
30
+ # These are common require path lists. This hash is used to optimize
31
+ # and consolidate require_path objects. Most specs just specify "lib"
32
+ # in their require paths, so lets take advantage of that by pre-allocating
33
+ # a require path list for that case.
34
+ REQUIRE_PATH_LIST = { # :nodoc:
35
+ 'lib' => ['lib'].freeze
36
+ }
37
+
38
+ def initialize data, extensions
39
+ parts = data[PREFIX.length..-1].split(" ".freeze, 4)
22
40
  @name = parts[0].freeze
23
41
  @version = Gem::Version.new parts[1]
24
42
  @platform = Gem::Platform.new parts[2]
25
- @require_paths = parts.drop(3).join(" ").split("\0")
43
+ @extensions = extensions
44
+ @full_name = if platform == Gem::Platform::RUBY
45
+ "#{name}-#{version}"
46
+ else
47
+ "#{name}-#{version}-#{platform}"
48
+ end
49
+
50
+ path_list = parts.last
51
+ @require_paths = REQUIRE_PATH_LIST[path_list] || path_list.split("\0".freeze).map! { |x|
52
+ REQUIRE_PATHS[x] || x
53
+ }
26
54
  end
27
55
  end
28
56
 
29
- def self.default_gemspec_stub filename
30
- new filename, true
57
+ def self.default_gemspec_stub filename, base_dir, gems_dir
58
+ new filename, base_dir, gems_dir, true
31
59
  end
32
60
 
33
- def self.gemspec_stub filename
34
- new filename, false
61
+ def self.gemspec_stub filename, base_dir, gems_dir
62
+ new filename, base_dir, gems_dir, false
35
63
  end
36
64
 
37
- def initialize filename, default_gem
65
+ attr_reader :base_dir, :gems_dir
66
+
67
+ def initialize filename, base_dir, gems_dir, default_gem
68
+ super()
38
69
  filename.untaint
39
70
 
40
71
  self.loaded_from = filename
41
72
  @data = nil
42
- @extensions = nil
43
73
  @name = nil
44
74
  @spec = nil
75
+ @base_dir = base_dir
76
+ @gems_dir = gems_dir
45
77
  @default_gem = default_gem
46
78
  end
47
79
 
@@ -56,6 +88,8 @@ class Gem::StubSpecification < Gem::BasicSpecification
56
88
  end
57
89
  end
58
90
 
91
+ def this; self; end
92
+
59
93
  def default_gem?
60
94
  @default_gem
61
95
  end
@@ -73,8 +107,6 @@ class Gem::StubSpecification < Gem::BasicSpecification
73
107
 
74
108
  def data
75
109
  unless @data
76
- @extensions = []
77
-
78
110
  begin
79
111
  saved_lineno = $.
80
112
  open loaded_from, OPEN_MODE do |file|
@@ -82,10 +114,13 @@ class Gem::StubSpecification < Gem::BasicSpecification
82
114
  file.readline # discard encoding line
83
115
  stubline = file.readline.chomp
84
116
  if stubline.start_with?(PREFIX) then
85
- @data = StubLine.new stubline
117
+ extensions = if /\A#{PREFIX}/ =~ file.readline.chomp
118
+ $'.split "\0"
119
+ else
120
+ StubLine::NO_EXTENSIONS
121
+ end
86
122
 
87
- @extensions = $'.split "\0" if
88
- /\A#{PREFIX}/ =~ file.readline.chomp
123
+ @data = StubLine.new stubline, extensions
89
124
  end
90
125
  rescue EOFError
91
126
  end
@@ -100,41 +135,14 @@ class Gem::StubSpecification < Gem::BasicSpecification
100
135
 
101
136
  private :data
102
137
 
103
- ##
104
- # Extensions for this gem
105
-
106
- def extensions
107
- return @extensions if @extensions
108
-
109
- data # load
110
-
111
- @extensions
112
- end
113
-
114
- ##
115
- # If a gem has a stub specification it doesn't need to bother with
116
- # compatibility with original_name gems. It was installed with the
117
- # normalized name.
118
-
119
- def find_full_gem_path # :nodoc:
120
- path = File.expand_path File.join gems_dir, full_name
121
- path.untaint
122
- path
123
- end
124
-
125
- ##
126
- # Full paths in the gem to add to <code>$LOAD_PATH</code> when this gem is
127
- # activated.
128
-
129
- def full_require_paths
130
- @require_paths ||= data.require_paths
131
-
132
- super
138
+ def raw_require_paths # :nodoc:
139
+ data.require_paths
133
140
  end
134
141
 
135
142
  def missing_extensions?
136
143
  return false if default_gem?
137
144
  return false if extensions.empty?
145
+ return false if File.exist? gem_build_complete_path
138
146
 
139
147
  to_spec.missing_extensions?
140
148
  end
@@ -154,12 +162,21 @@ class Gem::StubSpecification < Gem::BasicSpecification
154
162
  end
155
163
 
156
164
  ##
157
- # Require paths of the gem
165
+ # Extensions for this gem
158
166
 
159
- def require_paths
160
- @require_paths ||= data.require_paths
167
+ def extensions
168
+ data.extensions
169
+ end
161
170
 
162
- super
171
+ ##
172
+ # Version of the gem
173
+
174
+ def version
175
+ data.version
176
+ end
177
+
178
+ def full_name
179
+ data.full_name
163
180
  end
164
181
 
165
182
  ##
@@ -173,7 +190,7 @@ class Gem::StubSpecification < Gem::BasicSpecification
173
190
  end
174
191
 
175
192
  @spec ||= Gem::Specification.load(loaded_from)
176
- @spec.ignored = @ignored if instance_variable_defined? :@ignored
193
+ @spec.ignored = @ignored if @spec
177
194
 
178
195
  @spec
179
196
  end
@@ -186,13 +203,6 @@ class Gem::StubSpecification < Gem::BasicSpecification
186
203
  data
187
204
  end
188
205
 
189
- ##
190
- # Version of the gem
191
-
192
- def version
193
- @version ||= data.version
194
- end
195
-
196
206
  ##
197
207
  # Is there a stub line present for this StubSpecification?
198
208