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
@@ -67,6 +67,8 @@ class Gem::Resolver::ActivationRequest
67
67
  @spec.full_name
68
68
  end
69
69
 
70
+ alias_method :to_s, :full_name
71
+
70
72
  ##
71
73
  # The Gem::Specification for this activation request.
72
74
 
@@ -169,4 +171,3 @@ class Gem::Resolver::ActivationRequest
169
171
  end
170
172
 
171
173
  end
172
-
@@ -157,4 +157,3 @@ end
157
157
  # TODO: Remove in RubyGems 3
158
158
 
159
159
  Gem::Resolver::DependencyConflict = Gem::Resolver::Conflict # :nodoc:
160
-
@@ -67,6 +67,10 @@ class Gem::Resolver::DependencyRequest
67
67
  @dependency.name
68
68
  end
69
69
 
70
+ def type
71
+ @dependency.type
72
+ end
73
+
70
74
  ##
71
75
  # Indicate that the request is for a gem explicitly requested by the user
72
76
 
@@ -113,4 +117,3 @@ class Gem::Resolver::DependencyRequest
113
117
  end
114
118
 
115
119
  end
116
-
@@ -23,8 +23,7 @@ class Gem::Resolver::GitSpecification < Gem::Resolver::SpecSpecification
23
23
  def install options = {}
24
24
  require 'rubygems/installer'
25
25
 
26
- installer = Gem::Installer.new '', options
27
- installer.spec = spec
26
+ installer = Gem::Installer.for_spec spec, options
28
27
 
29
28
  yield installer if block_given?
30
29
 
@@ -0,0 +1 @@
1
+ require 'rubygems/resolver/molinillo/lib/molinillo'
@@ -0,0 +1,5 @@
1
+ require 'rubygems/resolver/molinillo/lib/molinillo/gem_metadata'
2
+ require 'rubygems/resolver/molinillo/lib/molinillo/errors'
3
+ require 'rubygems/resolver/molinillo/lib/molinillo/resolver'
4
+ require 'rubygems/resolver/molinillo/lib/molinillo/modules/ui'
5
+ require 'rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider'
@@ -0,0 +1,266 @@
1
+ require 'set'
2
+ require 'tsort'
3
+
4
+ module Gem::Resolver::Molinillo
5
+ # A directed acyclic graph that is tuned to hold named dependencies
6
+ class DependencyGraph
7
+ include Enumerable
8
+
9
+ # Enumerates through the vertices of the graph.
10
+ # @return [Array<Vertex>] The graph's vertices.
11
+ def each
12
+ vertices.values.each { |v| yield v }
13
+ end
14
+
15
+ include TSort
16
+
17
+ alias_method :tsort_each_node, :each
18
+
19
+ def tsort_each_child(vertex, &block)
20
+ vertex.successors.each(&block)
21
+ end
22
+
23
+ # Topologically sorts the given vertices.
24
+ # @param [Enumerable<Vertex>] vertices the vertices to be sorted, which must
25
+ # all belong to the same graph.
26
+ # @return [Array<Vertex>] The sorted vertices.
27
+ def self.tsort(vertices)
28
+ TSort.tsort(
29
+ lambda { |b| vertices.each(&b) },
30
+ lambda { |v, &b| (v.successors & vertices).each(&b) }
31
+ )
32
+ end
33
+
34
+ # A directed edge of a {DependencyGraph}
35
+ # @attr [Vertex] origin The origin of the directed edge
36
+ # @attr [Vertex] destination The destination of the directed edge
37
+ # @attr [Array] requirements The requirements the directed edge represents
38
+ Edge = Struct.new(:origin, :destination, :requirements)
39
+
40
+ # @return [{String => Vertex}] vertices that have no {Vertex#predecessors},
41
+ # keyed by by {Vertex#name}
42
+ attr_reader :root_vertices
43
+ # @return [{String => Vertex}] the vertices of the dependency graph, keyed
44
+ # by {Vertex#name}
45
+ attr_reader :vertices
46
+ # @return [Set<Edge>] the edges of the dependency graph
47
+ attr_reader :edges
48
+
49
+ def initialize
50
+ @vertices = {}
51
+ @edges = Set.new
52
+ @root_vertices = {}
53
+ end
54
+
55
+ # Initializes a copy of a {DependencyGraph}, ensuring that all {#vertices}
56
+ # have the correct {Vertex#graph} set
57
+ def initialize_copy(other)
58
+ super
59
+ @vertices = other.vertices.reduce({}) do |vertices, (name, vertex)|
60
+ vertices.tap do |hash|
61
+ hash[name] = vertex.dup.tap { |v| v.graph = self }
62
+ end
63
+ end
64
+ @root_vertices = Hash[@vertices.select { |n, _v| other.root_vertices[n] }]
65
+ @edges = other.edges.map do |edge|
66
+ Edge.new(
67
+ vertex_named(edge.origin.name),
68
+ vertex_named(edge.destination.name),
69
+ edge.requirements.dup
70
+ )
71
+ end
72
+ end
73
+
74
+ # @return [String] a string suitable for debugging
75
+ def inspect
76
+ "#{self.class}:#{vertices.values.inspect}"
77
+ end
78
+
79
+ # @return [Boolean] whether the two dependency graphs are equal, determined
80
+ # by a recursive traversal of each {#root_vertices} and its
81
+ # {Vertex#successors}
82
+ def ==(other)
83
+ root_vertices == other.root_vertices
84
+ end
85
+
86
+ # @param [String] name
87
+ # @param [Object] payload
88
+ # @param [Array<String>] parent_names
89
+ # @param [Object] requirement the requirement that is requiring the child
90
+ # @return [void]
91
+ def add_child_vertex(name, payload, parent_names, requirement)
92
+ is_root = parent_names.include?(nil)
93
+ parent_nodes = parent_names.compact.map { |n| vertex_named(n) }
94
+ vertex = vertex_named(name) || if is_root
95
+ add_root_vertex(name, payload)
96
+ else
97
+ add_vertex(name, payload)
98
+ end
99
+ vertex.payload ||= payload
100
+ parent_nodes.each do |parent_node|
101
+ add_edge(parent_node, vertex, requirement)
102
+ end
103
+ vertex
104
+ end
105
+
106
+ # @param [String] name
107
+ # @param [Object] payload
108
+ # @return [Vertex] the vertex that was added to `self`
109
+ def add_vertex(name, payload)
110
+ vertex = vertices[name] ||= Vertex.new(self, name, payload)
111
+ vertex.tap { |v| v.payload = payload }
112
+ end
113
+
114
+ # @param [String] name
115
+ # @param [Object] payload
116
+ # @return [Vertex] the vertex that was added to `self`
117
+ def add_root_vertex(name, payload)
118
+ add_vertex(name, payload).tap { |v| root_vertices[name] = v }
119
+ end
120
+
121
+ # Detaches the {#vertex_named} `name` {Vertex} from the graph, recursively
122
+ # removing any non-root vertices that were orphaned in the process
123
+ # @param [String] name
124
+ # @return [void]
125
+ def detach_vertex_named(name)
126
+ vertex = vertex_named(name)
127
+ return unless vertex
128
+ successors = vertex.successors
129
+ vertices.delete(name)
130
+ edges.reject! { |e| e.origin == vertex || e.destination == vertex }
131
+ successors.each { |v| detach_vertex_named(v.name) unless root_vertices[v.name] || v.predecessors.any? }
132
+ end
133
+
134
+ # @param [String] name
135
+ # @return [Vertex,nil] the vertex with the given name
136
+ def vertex_named(name)
137
+ vertices[name]
138
+ end
139
+
140
+ # @param [String] name
141
+ # @return [Vertex,nil] the root vertex with the given name
142
+ def root_vertex_named(name)
143
+ root_vertices[name]
144
+ end
145
+
146
+ # Adds a new {Edge} to the dependency graph
147
+ # @param [Vertex] origin
148
+ # @param [Vertex] destination
149
+ # @param [Object] requirement the requirement that this edge represents
150
+ # @return [Edge] the added edge
151
+ def add_edge(origin, destination, requirement)
152
+ if origin == destination || destination.path_to?(origin)
153
+ raise CircularDependencyError.new([origin, destination])
154
+ end
155
+ Edge.new(origin, destination, [requirement]).tap { |e| edges << e }
156
+ end
157
+
158
+ # A vertex in a {DependencyGraph} that encapsulates a {#name} and a
159
+ # {#payload}
160
+ class Vertex
161
+ # @return [DependencyGraph] the graph this vertex is a node of
162
+ attr_accessor :graph
163
+
164
+ # @return [String] the name of the vertex
165
+ attr_accessor :name
166
+
167
+ # @return [Object] the payload the vertex holds
168
+ attr_accessor :payload
169
+
170
+ # @return [Arrary<Object>] the explicit requirements that required
171
+ # this vertex
172
+ attr_reader :explicit_requirements
173
+
174
+ # @param [DependencyGraph] graph see {#graph}
175
+ # @param [String] name see {#name}
176
+ # @param [Object] payload see {#payload}
177
+ def initialize(graph, name, payload)
178
+ @graph = graph
179
+ @name = name
180
+ @payload = payload
181
+ @explicit_requirements = []
182
+ end
183
+
184
+ # @return [Array<Object>] all of the requirements that required
185
+ # this vertex
186
+ def requirements
187
+ incoming_edges.map(&:requirements).flatten + explicit_requirements
188
+ end
189
+
190
+ # @return [Array<Edge>] the edges of {#graph} that have `self` as their
191
+ # {Edge#origin}
192
+ def outgoing_edges
193
+ graph.edges.select { |e| e.origin.shallow_eql?(self) }
194
+ end
195
+
196
+ # @return [Array<Edge>] the edges of {#graph} that have `self` as their
197
+ # {Edge#destination}
198
+ def incoming_edges
199
+ graph.edges.select { |e| e.destination.shallow_eql?(self) }
200
+ end
201
+
202
+ # @return [Set<Vertex>] the vertices of {#graph} that have an edge with
203
+ # `self` as their {Edge#destination}
204
+ def predecessors
205
+ incoming_edges.map(&:origin).to_set
206
+ end
207
+
208
+ # @return [Set<Vertex>] the vertices of {#graph} that have an edge with
209
+ # `self` as their {Edge#origin}
210
+ def successors
211
+ outgoing_edges.map(&:destination).to_set
212
+ end
213
+
214
+ # @return [Set<Vertex>] the vertices of {#graph} where `self` is an
215
+ # {#ancestor?}
216
+ def recursive_successors
217
+ successors + successors.map(&:recursive_successors).reduce(Set.new, &:+)
218
+ end
219
+
220
+ # @return [String] a string suitable for debugging
221
+ def inspect
222
+ "#{self.class}:#{name}(#{payload.inspect})"
223
+ end
224
+
225
+ # @return [Boolean] whether the two vertices are equal, determined
226
+ # by a recursive traversal of each {Vertex#successors}
227
+ def ==(other)
228
+ shallow_eql?(other) &&
229
+ successors == other.successors
230
+ end
231
+
232
+ # @return [Boolean] whether the two vertices are equal, determined
233
+ # solely by {#name} and {#payload} equality
234
+ def shallow_eql?(other)
235
+ other &&
236
+ name == other.name &&
237
+ payload == other.payload
238
+ end
239
+
240
+ alias_method :eql?, :==
241
+
242
+ # @return [Fixnum] a hash for the vertex based upon its {#name}
243
+ def hash
244
+ name.hash
245
+ end
246
+
247
+ # Is there a path from `self` to `other` following edges in the
248
+ # dependency graph?
249
+ # @return true iff there is a path following edges within this {#graph}
250
+ def path_to?(other)
251
+ successors.include?(other) || successors.any? { |v| v.path_to?(other) }
252
+ end
253
+
254
+ alias_method :descendent?, :path_to?
255
+
256
+ # Is there a path from `other` to `self` following edges in the
257
+ # dependency graph?
258
+ # @return true iff there is a path following edges within this {#graph}
259
+ def ancestor?(other)
260
+ predecessors.include?(other) || predecessors.any? { |v| v.ancestor?(other) }
261
+ end
262
+
263
+ alias_method :is_reachable_from?, :ancestor?
264
+ end
265
+ end
266
+ end
@@ -0,0 +1,69 @@
1
+ module Gem::Resolver::Molinillo
2
+ # An error that occurred during the resolution process
3
+ class ResolverError < StandardError; end
4
+
5
+ # An error caused by searching for a dependency that is completely unknown,
6
+ # i.e. has no versions available whatsoever.
7
+ class NoSuchDependencyError < ResolverError
8
+ # @return [Object] the dependency that could not be found
9
+ attr_accessor :dependency
10
+
11
+ # @return [Array<Object>] the specifications that depended upon {#dependency}
12
+ attr_accessor :required_by
13
+
14
+ # @param [Object] dependency @see {#dependency}
15
+ # @param [Array<Object>] required_by @see {#required_by}
16
+ def initialize(dependency, required_by = [])
17
+ @dependency = dependency
18
+ @required_by = required_by
19
+ super()
20
+ end
21
+
22
+ def message
23
+ sources = required_by.map { |r| "`#{r}`" }.join(' and ')
24
+ message = "Unable to find a specification for `#{dependency}`"
25
+ message << " depended upon by #{sources}" unless sources.empty?
26
+ message
27
+ end
28
+ end
29
+
30
+ # An error caused by attempting to fulfil a dependency that was circular
31
+ #
32
+ # @note This exception will be thrown iff a {Vertex} is added to a
33
+ # {DependencyGraph} that has a {DependencyGraph::Vertex#path_to?} an
34
+ # existing {DependencyGraph::Vertex}
35
+ class CircularDependencyError < ResolverError
36
+ # [Set<Object>] the dependencies responsible for causing the error
37
+ attr_reader :dependencies
38
+
39
+ # @param [Array<DependencyGraph::Vertex>] nodes the nodes in the dependency
40
+ # that caused the error
41
+ def initialize(nodes)
42
+ super "There is a circular dependency between #{nodes.map(&:name).join(' and ')}"
43
+ @dependencies = nodes.map(&:payload).to_set
44
+ end
45
+ end
46
+
47
+ # An error caused by conflicts in version
48
+ class VersionConflict < ResolverError
49
+ # @return [{String => Resolution::Conflict}] the conflicts that caused
50
+ # resolution to fail
51
+ attr_reader :conflicts
52
+
53
+ # @param [{String => Resolution::Conflict}] conflicts see {#conflicts}
54
+ def initialize(conflicts)
55
+ pairs = []
56
+ conflicts.values.flatten.map(&:requirements).flatten.each do |conflicting|
57
+ conflicting.each do |source, conflict_requirements|
58
+ conflict_requirements.each do |c|
59
+ pairs << [c, source]
60
+ end
61
+ end
62
+ end
63
+
64
+ super "Unable to satisfy the following requirements:\n\n" \
65
+ "#{pairs.map { |r, d| "- `#{r}` required by `#{d}`" }.join("\n")}"
66
+ @conflicts = conflicts
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,3 @@
1
+ module Gem::Resolver::Molinillo
2
+ VERSION = '0.3.0'
3
+ end
@@ -0,0 +1,99 @@
1
+ module Gem::Resolver::Molinillo
2
+ # Provides information about specifcations and dependencies to the resolver,
3
+ # allowing the {Resolver} class to remain generic while still providing power
4
+ # and flexibility.
5
+ #
6
+ # This module contains the methods that users of Gem::Resolver::Molinillo must to implement,
7
+ # using knowledge of their own model classes.
8
+ module SpecificationProvider
9
+ # Search for the specifications that match the given dependency.
10
+ # The specifications in the returned array will be considered in reverse
11
+ # order, so the latest version ought to be last.
12
+ # @note This method should be 'pure', i.e. the return value should depend
13
+ # only on the `dependency` parameter.
14
+ #
15
+ # @param [Object] dependency
16
+ # @return [Array<Object>] the specifications that satisfy the given
17
+ # `dependency`.
18
+ def search_for(dependency)
19
+ []
20
+ end
21
+
22
+ # Returns the dependencies of `specification`.
23
+ # @note This method should be 'pure', i.e. the return value should depend
24
+ # only on the `specification` parameter.
25
+ #
26
+ # @param [Object] specification
27
+ # @return [Array<Object>] the dependencies that are required by the given
28
+ # `specification`.
29
+ def dependencies_for(specification)
30
+ []
31
+ end
32
+
33
+ # Determines whether the given `requirement` is satisfied by the given
34
+ # `spec`, in the context of the current `activated` dependency graph.
35
+ #
36
+ # @param [Object] requirement
37
+ # @param [DependencyGraph] activated the current dependency graph in the
38
+ # resolution process.
39
+ # @param [Object] spec
40
+ # @return [Boolean] whether `requirement` is satisfied by `spec` in the
41
+ # context of the current `activated` dependency graph.
42
+ def requirement_satisfied_by?(requirement, activated, spec)
43
+ true
44
+ end
45
+
46
+ # Returns the name for the given `dependency`.
47
+ # @note This method should be 'pure', i.e. the return value should depend
48
+ # only on the `dependency` parameter.
49
+ #
50
+ # @param [Object] dependency
51
+ # @return [String] the name for the given `dependency`.
52
+ def name_for(dependency)
53
+ dependency.to_s
54
+ end
55
+
56
+ # @return [String] the name of the source of explicit dependencies, i.e.
57
+ # those passed to {Resolver#resolve} directly.
58
+ def name_for_explicit_dependency_source
59
+ 'user-specified dependency'
60
+ end
61
+
62
+ # @return [String] the name of the source of 'locked' dependencies, i.e.
63
+ # those passed to {Resolver#resolve} directly as the `base`
64
+ def name_for_locking_dependency_source
65
+ 'Lockfile'
66
+ end
67
+
68
+ # Sort dependencies so that the ones that are easiest to resolve are first.
69
+ # Easiest to resolve is (usually) defined by:
70
+ # 1) Is this dependency already activated?
71
+ # 2) How relaxed are the requirements?
72
+ # 3) Are there any conflicts for this dependency?
73
+ # 4) How many possibilities are there to satisfy this dependency?
74
+ #
75
+ # @param [Array<Object>] dependencies
76
+ # @param [DependencyGraph] activated the current dependency graph in the
77
+ # resolution process.
78
+ # @param [{String => Array<Conflict>}] conflicts
79
+ # @return [Array<Object>] a sorted copy of `dependencies`.
80
+ def sort_dependencies(dependencies, activated, conflicts)
81
+ dependencies.sort_by do |dependency|
82
+ name = name_for(dependency)
83
+ [
84
+ activated.vertex_named(name).payload ? 0 : 1,
85
+ conflicts[name] ? 0 : 1,
86
+ ]
87
+ end
88
+ end
89
+
90
+ # Returns whether this dependency, which has no possible matching
91
+ # specifications, can safely be ignored.
92
+ #
93
+ # @param [Object] dependency
94
+ # @return [Boolean] whether this dependency can safely be skipped.
95
+ def allow_missing?(dependency)
96
+ false
97
+ end
98
+ end
99
+ end