molinillo 0.6.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 5b31401d705c0bd1b9839f3b560996af5339a632
4
- data.tar.gz: daabc784cc8a0385da64f2befa949887c70e3502
2
+ SHA256:
3
+ metadata.gz: e6828b175f84c2dae7fadfaf7c614a3a6198089a11f0e2c20defc697b1108e2b
4
+ data.tar.gz: b4e8a71693257b7726be5c21fee26571197b0cd69b1445bb51107aad984b0e89
5
5
  SHA512:
6
- metadata.gz: 139afb59678e775ae0e93214dfa78e13f1da4b4e73a42b514ab696818cfa00947e57b16a01b4582dbbc2563c222166c3779e032e899244cebf95f4573259ee7b
7
- data.tar.gz: 708818cffc500e0f686a51e6025d254150408e206d48e176b5fa97d6466bd8efcf3897ab6fc4f21602197e5c1ac56b5f623b796617741451be77f5d182126ca0
6
+ metadata.gz: 67df28dfe97c6a0b66d96df61e543fa917de1bd63e2ffa169d8499f62940722a72629b37fe1c7a8db4408d7dfbfc8d718ceac09956a5160c875d74db23ab15cf
7
+ data.tar.gz: d750b24f9a1dd5a4a2a846f00c1ef0f6e05fdff166266a9427c9918254ff991c8bc0fb7fae861ec172ac0a305942981d0c991932a282522e2bb0eb7c981a1b13
@@ -33,7 +33,7 @@ This stack-based approach is used because backtracking (also known as *unwinding
33
33
  13. If there is an existing, `activated` vertex for the dependency, `attempt_to_filter_existing_spec`
34
34
  - This filters the contents of the existing vertex's `PossibilitySet` by the current state's `requirement`
35
35
  - If any possibilities remain within the `PossibilitySet`, it updates the activated vertex's payload with the new, filtered state and pushes a new `DependencyState`
36
- - If no possibilities remain within the `PossibilitySet` after filtering, or if the current state's `PossibilitySet` had a different set of sub-dependecy requirements to the existing vertex's `PossibilitySet`, `create_conflict` and `unwind_for_conflict`, back to the last `DependencyState` that has a chance to not generate a conflict. Go to #6
36
+ - If no possibilities remain within the `PossibilitySet` after filtering, or if the current state's `PossibilitySet` had a different set of sub-dependency requirements to the existing vertex's `PossibilitySet`, `create_conflict` and `unwind_for_conflict`, back to the last `DependencyState` that has a chance to not generate a conflict. Go to #6
37
37
  15. Terminate with the topmost state's dependency graph when there are no more requirements left
38
38
  16. For each vertex with a payload of allowable versions for this resolution (i.e., a `PossibilitySet`), pick a single specific version.
39
39
 
@@ -52,7 +52,7 @@ the previous unwinds that have determined our current state.
52
52
  1. First, consider the current conflict as follows:
53
53
  - Find the earliest (lowest index) set of requirements which combine to cause
54
54
  the conflict. Any non-binding requirements can be ignored, as removing them
55
- would not resolve the current onflict
55
+ would not resolve the current conflict
56
56
  - For each binding requirement, find all the alternative possibilities that
57
57
  would relax the requirement:
58
58
  - the requirement's DependencyState might have alternative possibilities
@@ -79,7 +79,7 @@ different, smaller unwind was chosen instead):
79
79
  error as resolution is not possible.
80
80
  3b. Filter the state that we're unwinding to, in order to remove any
81
81
  possibilities we know will result in a conflict. Consider all possible unwinds
82
- to the chosen state (there may be several, amasssed from previous unused
82
+ to the chosen state (there may be several, amassed from previous unused
83
83
  unwinds for different conflicts) when doing this filtering - only
84
84
  possibilities that will certainly result in *all* of those conflicts can be
85
85
  filtered out as having no chance of resolution
@@ -1,5 +1,83 @@
1
1
  # Molinillo Changelog
2
2
 
3
+ ## 0.7.0 (2020-10-21)
4
+
5
+ ##### Breaking
6
+
7
+ * Support for Ruby 1.8.7 and 1.9.3 has been dropped, the minimum supported
8
+ Ruby version is now 2.0.
9
+ [Samuel Giddins](https://github.com/segiddins)
10
+
11
+ ##### Enhancements
12
+
13
+ * Circular dependency errors include the full (shortest) path between the
14
+ circularly-dependent vertices.
15
+ [Samuel Giddins](https://github.com/segiddins)
16
+
17
+ ##### Bug Fixes
18
+
19
+ * None.
20
+
21
+
22
+ ## 0.6.6 (2018-08-07)
23
+
24
+ ##### Enhancements
25
+
26
+ * Improve performance of `Vertex#path_to?`.
27
+ [Samuel Giddins](https://github.com/segiddins)
28
+
29
+ * Allow customization of string used to say that a version conflict has occurred
30
+ for a particular name by passing in the `:incompatible_version_message_for_conflict`
31
+ key when constructing a version conflict message with trees.
32
+ [Samuel Giddins](https://github.com/segiddins)
33
+
34
+ ##### Bug Fixes
35
+
36
+ * None.
37
+
38
+
39
+ ## 0.6.5 (2018-03-22)
40
+
41
+ ##### Enhancements
42
+
43
+ * Improve performance of recursive vertex methods.
44
+ [Samuel Giddins](https://github.com/segiddins)
45
+
46
+ ##### Bug Fixes
47
+
48
+ * None.
49
+
50
+
51
+ ## 0.6.4 (2017-10-29)
52
+
53
+ ##### Enhancements
54
+
55
+ * Reduce memory usage during resolution by making the `Vertex#requirements`
56
+ array unique.
57
+ [Grey Baker](https://github.com/greysteil)
58
+ [Jan Krutisch](https://github.com/halfbyte)
59
+
60
+ ##### Bug Fixes
61
+
62
+ * None.
63
+
64
+
65
+ ## 0.6.3 (2017-09-06)
66
+
67
+ ##### Enhancements
68
+
69
+ * None.
70
+
71
+ ##### Bug Fixes
72
+
73
+ * Handle the case where an unwind occurs to a requirement that directly caused
74
+ the current conflict but could also have been unwound to directly from
75
+ previous conflicts. In this case, filtering must not remove any possibilities
76
+ that could have avoided the previous conflicts (even if they would not avoid
77
+ the current one).
78
+ [Grey Baker](https://github.com/greysteil)
79
+
80
+
3
81
  ## 0.6.2 (2017-08-25)
4
82
 
5
83
  ##### Enhancements
data/README.md CHANGED
@@ -28,8 +28,7 @@ $ gem install molinillo
28
28
 
29
29
  ## Usage
30
30
 
31
- See the [ARCHITECTURE](ARCHITECTURE.md) file for an overview and look at the test suite for example usage. Better documentation and examples are
32
- forthcoming.
31
+ See the [ARCHITECTURE](ARCHITECTURE.md) file for an overview and look at the test suite for example usage.
33
32
 
34
33
  ## Contributing
35
34
 
@@ -1,11 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'molinillo/compatibility'
4
- require 'molinillo/gem_metadata'
5
- require 'molinillo/errors'
6
- require 'molinillo/resolver'
7
- require 'molinillo/modules/ui'
8
- require 'molinillo/modules/specification_provider'
3
+ require_relative 'molinillo/gem_metadata'
4
+ require_relative 'molinillo/errors'
5
+ require_relative 'molinillo/resolver'
6
+ require_relative 'molinillo/modules/ui'
7
+ require_relative 'molinillo/modules/specification_provider'
9
8
 
10
9
  # Molinillo is a generic dependency resolution algorithm.
11
10
  module Molinillo
@@ -3,8 +3,8 @@
3
3
  require 'set'
4
4
  require 'tsort'
5
5
 
6
- require 'molinillo/dependency_graph/log'
7
- require 'molinillo/dependency_graph/vertex'
6
+ require_relative 'dependency_graph/log'
7
+ require_relative 'dependency_graph/vertex'
8
8
 
9
9
  module Molinillo
10
10
  # A directed acyclic graph that is tuned to hold named dependencies
@@ -124,6 +124,7 @@ module Molinillo
124
124
  dot.join("\n")
125
125
  end
126
126
 
127
+ # @param [DependencyGraph] other
127
128
  # @return [Boolean] whether the two dependency graphs are equal, determined
128
129
  # by a recursive traversal of each {#root_vertices} and its
129
130
  # {Vertex#successors}
@@ -190,7 +191,7 @@ module Molinillo
190
191
  # @return [Edge] the added edge
191
192
  def add_edge(origin, destination, requirement)
192
193
  if destination.path_to?(origin)
193
- raise CircularDependencyError.new([origin, destination])
194
+ raise CircularDependencyError.new(path(destination, origin))
194
195
  end
195
196
  add_edge_no_circular(origin, destination, requirement)
196
197
  end
@@ -219,5 +220,37 @@ module Molinillo
219
220
  def add_edge_no_circular(origin, destination, requirement)
220
221
  log.add_edge_no_circular(self, origin.name, destination.name, requirement)
221
222
  end
223
+
224
+ # Returns the path between two vertices
225
+ # @raise [ArgumentError] if there is no path between the vertices
226
+ # @param [Vertex] from
227
+ # @param [Vertex] to
228
+ # @return [Array<Vertex>] the shortest path from `from` to `to`
229
+ def path(from, to)
230
+ distances = Hash.new(vertices.size + 1)
231
+ distances[from.name] = 0
232
+ predecessors = {}
233
+ each do |vertex|
234
+ vertex.successors.each do |successor|
235
+ if distances[successor.name] > distances[vertex.name] + 1
236
+ distances[successor.name] = distances[vertex.name] + 1
237
+ predecessors[successor] = vertex
238
+ end
239
+ end
240
+ end
241
+
242
+ path = [to]
243
+ while before = predecessors[to]
244
+ path << before
245
+ to = before
246
+ break if to == from
247
+ end
248
+
249
+ unless path.last.equal?(from)
250
+ raise ArgumentError, "There is no path from #{from.name} to #{to.name}"
251
+ end
252
+
253
+ path.reverse
254
+ end
222
255
  end
223
256
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'molinillo/dependency_graph/action'
3
+ require_relative 'action'
4
4
  module Molinillo
5
5
  class DependencyGraph
6
6
  # @!visibility private
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'molinillo/dependency_graph/action'
3
+ require_relative 'action'
4
4
  module Molinillo
5
5
  class DependencyGraph
6
6
  # @!visibility private
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'molinillo/dependency_graph/action'
3
+ require_relative 'action'
4
4
  module Molinillo
5
5
  class DependencyGraph
6
6
  # @!visibility private
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'molinillo/dependency_graph/action'
3
+ require_relative 'action'
4
4
  module Molinillo
5
5
  class DependencyGraph
6
6
  # @!visibility private
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'molinillo/dependency_graph/add_edge_no_circular'
4
- require 'molinillo/dependency_graph/add_vertex'
5
- require 'molinillo/dependency_graph/delete_edge'
6
- require 'molinillo/dependency_graph/detach_vertex_named'
7
- require 'molinillo/dependency_graph/set_payload'
8
- require 'molinillo/dependency_graph/tag'
3
+ require_relative 'add_edge_no_circular'
4
+ require_relative 'add_vertex'
5
+ require_relative 'delete_edge'
6
+ require_relative 'detach_vertex_named'
7
+ require_relative 'set_payload'
8
+ require_relative 'tag'
9
9
 
10
10
  module Molinillo
11
11
  class DependencyGraph
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'molinillo/dependency_graph/action'
3
+ require_relative 'action'
4
4
  module Molinillo
5
5
  class DependencyGraph
6
6
  # @!visibility private
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'molinillo/dependency_graph/action'
3
+ require_relative 'action'
4
4
  module Molinillo
5
5
  class DependencyGraph
6
6
  # @!visibility private
@@ -14,11 +14,11 @@ module Molinillo
14
14
  end
15
15
 
16
16
  # (see Action#up)
17
- def up(_graph)
17
+ def up(graph)
18
18
  end
19
19
 
20
20
  # (see Action#down)
21
- def down(_graph)
21
+ def down(graph)
22
22
  end
23
23
 
24
24
  # @!group Tag
@@ -33,7 +33,7 @@ module Molinillo
33
33
  # @return [Array<Object>] all of the requirements that required
34
34
  # this vertex
35
35
  def requirements
36
- incoming_edges.map(&:requirement) + explicit_requirements
36
+ (incoming_edges.map(&:requirement) + explicit_requirements).uniq
37
37
  end
38
38
 
39
39
  # @return [Array<Edge>] the edges of {#graph} that have `self` as their
@@ -50,14 +50,25 @@ module Molinillo
50
50
  incoming_edges.map(&:origin)
51
51
  end
52
52
 
53
- # @return [Array<Vertex>] the vertices of {#graph} where `self` is a
53
+ # @return [Set<Vertex>] the vertices of {#graph} where `self` is a
54
54
  # {#descendent?}
55
55
  def recursive_predecessors
56
- vertices = predecessors
57
- vertices += Compatibility.flat_map(vertices, &:recursive_predecessors)
58
- vertices.uniq!
56
+ _recursive_predecessors
57
+ end
58
+
59
+ # @param [Set<Vertex>] vertices the set to add the predecessors to
60
+ # @return [Set<Vertex>] the vertices of {#graph} where `self` is a
61
+ # {#descendent?}
62
+ def _recursive_predecessors(vertices = Set.new)
63
+ incoming_edges.each do |edge|
64
+ vertex = edge.origin
65
+ next unless vertices.add?(vertex)
66
+ vertex._recursive_predecessors(vertices)
67
+ end
68
+
59
69
  vertices
60
70
  end
71
+ protected :_recursive_predecessors
61
72
 
62
73
  # @return [Array<Vertex>] the vertices of {#graph} that have an edge with
63
74
  # `self` as their {Edge#origin}
@@ -65,14 +76,25 @@ module Molinillo
65
76
  outgoing_edges.map(&:destination)
66
77
  end
67
78
 
68
- # @return [Array<Vertex>] the vertices of {#graph} where `self` is an
79
+ # @return [Set<Vertex>] the vertices of {#graph} where `self` is an
69
80
  # {#ancestor?}
70
81
  def recursive_successors
71
- vertices = successors
72
- vertices += Compatibility.flat_map(vertices, &:recursive_successors)
73
- vertices.uniq!
82
+ _recursive_successors
83
+ end
84
+
85
+ # @param [Set<Vertex>] vertices the set to add the successors to
86
+ # @return [Set<Vertex>] the vertices of {#graph} where `self` is an
87
+ # {#ancestor?}
88
+ def _recursive_successors(vertices = Set.new)
89
+ outgoing_edges.each do |edge|
90
+ vertex = edge.destination
91
+ next unless vertices.add?(vertex)
92
+ vertex._recursive_successors(vertices)
93
+ end
94
+
74
95
  vertices
75
96
  end
97
+ protected :_recursive_successors
76
98
 
77
99
  # @return [String] a string suitable for debugging
78
100
  def inspect
@@ -108,11 +130,21 @@ module Molinillo
108
130
  # dependency graph?
109
131
  # @return true iff there is a path following edges within this {#graph}
110
132
  def path_to?(other)
111
- equal?(other) || successors.any? { |v| v.path_to?(other) }
133
+ _path_to?(other)
112
134
  end
113
135
 
114
136
  alias descendent? path_to?
115
137
 
138
+ # @param [Vertex] other the vertex to check if there's a path to
139
+ # @param [Set<Vertex>] visited the vertices of {#graph} that have been visited
140
+ # @return [Boolean] whether there is a path to `other` from `self`
141
+ def _path_to?(other, visited = Set.new)
142
+ return false unless visited.add?(self)
143
+ return true if equal?(other)
144
+ successors.any? { |v| v._path_to?(other, visited) }
145
+ end
146
+ protected :_path_to?
147
+
116
148
  # Is there a path from `other` to `self` following edges in the
117
149
  # dependency graph?
118
150
  # @return true iff there is a path following edges within this {#graph}
@@ -18,7 +18,7 @@ module Molinillo
18
18
  # @param [Array<Object>] required_by @see {#required_by}
19
19
  def initialize(dependency, required_by = [])
20
20
  @dependency = dependency
21
- @required_by = required_by
21
+ @required_by = required_by.uniq
22
22
  super()
23
23
  end
24
24
 
@@ -65,7 +65,7 @@ module Molinillo
65
65
  # @param [SpecificationProvider] specification_provider see {#specification_provider}
66
66
  def initialize(conflicts, specification_provider)
67
67
  pairs = []
68
- Compatibility.flat_map(conflicts.values.flatten, &:requirements).each do |conflicting|
68
+ conflicts.values.flat_map(&:requirements).each do |conflicting|
69
69
  conflicting.each do |source, conflict_requirements|
70
70
  conflict_requirements.each do |c|
71
71
  pairs << [c, source]
@@ -80,7 +80,7 @@ module Molinillo
80
80
  @specification_provider = specification_provider
81
81
  end
82
82
 
83
- require 'molinillo/delegates/specification_provider'
83
+ require_relative 'delegates/specification_provider'
84
84
  include Delegates::SpecificationProvider
85
85
 
86
86
  # @return [String] An error message that includes requirement trees,
@@ -101,9 +101,14 @@ module Molinillo
101
101
  printable_requirement = opts.delete(:printable_requirement) { proc { |req| req.to_s } }
102
102
  additional_message_for_conflict = opts.delete(:additional_message_for_conflict) { proc {} }
103
103
  version_for_spec = opts.delete(:version_for_spec) { proc(&:to_s) }
104
+ incompatible_version_message_for_conflict = opts.delete(:incompatible_version_message_for_conflict) do
105
+ proc do |name, _conflict|
106
+ %(#{solver_name} could not find compatible versions for #{possibility_type} "#{name}":)
107
+ end
108
+ end
104
109
 
105
110
  conflicts.sort.reduce(''.dup) do |o, (name, conflict)|
106
- o << %(\n#{solver_name} could not find compatible versions for #{possibility_type} "#{name}":\n)
111
+ o << "\n" << incompatible_version_message_for_conflict.call(name, conflict) << "\n"
107
112
  if conflict.locked_requirement
108
113
  o << %( In snapshot (#{name_for_locking_dependency_source}):\n)
109
114
  o << %( #{printable_requirement.call(conflict.locked_requirement)}\n)
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Molinillo
4
4
  # The version of Molinillo.
5
- VERSION = '0.6.2'.freeze
5
+ VERSION = '0.7.0'.freeze
6
6
  end
@@ -207,7 +207,7 @@ module Molinillo
207
207
  def start_resolution
208
208
  @started_at = Time.now
209
209
 
210
- handle_missing_or_push_dependency_state(initial_state)
210
+ push_initial_state
211
211
 
212
212
  debug { "Starting resolution (#{@started_at})\nUser-requested dependencies: #{original_requested}" }
213
213
  resolver_ui.before_resolution
@@ -218,7 +218,7 @@ module Molinillo
218
218
  next unless vertex.payload
219
219
 
220
220
  latest_version = vertex.payload.possibilities.reverse_each.find do |possibility|
221
- vertex.requirements.uniq.all? { |req| requirement_satisfied_by?(req, activated, possibility) }
221
+ vertex.requirements.all? { |req| requirement_satisfied_by?(req, activated, possibility) }
222
222
  end
223
223
 
224
224
  activated.set_payload(vertex.name, latest_version)
@@ -238,11 +238,11 @@ module Molinillo
238
238
  debug { 'Activated: ' + Hash[activated.vertices.select { |_n, v| v.payload }].keys.join(', ') } if state
239
239
  end
240
240
 
241
- require 'molinillo/state'
242
- require 'molinillo/modules/specification_provider'
241
+ require_relative 'state'
242
+ require_relative 'modules/specification_provider'
243
243
 
244
- require 'molinillo/delegates/resolution_state'
245
- require 'molinillo/delegates/specification_provider'
244
+ require_relative 'delegates/resolution_state'
245
+ require_relative 'delegates/specification_provider'
246
246
 
247
247
  include Molinillo::Delegates::ResolutionState
248
248
  include Molinillo::Delegates::SpecificationProvider
@@ -273,10 +273,10 @@ module Molinillo
273
273
  states.last
274
274
  end
275
275
 
276
- # Creates the initial state for the resolution, based upon the
276
+ # Creates and pushes the initial state for the resolution, based upon the
277
277
  # {#requested} dependencies
278
- # @return [DependencyState] the initial state for the resolution
279
- def initial_state
278
+ # @return [void]
279
+ def push_initial_state
280
280
  graph = DependencyGraph.new.tap do |dg|
281
281
  original_requested.each do |requested|
282
282
  vertex = dg.add_vertex(name_for(requested), nil, true)
@@ -285,18 +285,7 @@ module Molinillo
285
285
  dg.tag(:initial_state)
286
286
  end
287
287
 
288
- requirements = sort_dependencies(original_requested, graph, {})
289
- initial_requirement = requirements.shift
290
- DependencyState.new(
291
- initial_requirement && name_for(initial_requirement),
292
- requirements,
293
- graph,
294
- initial_requirement,
295
- possibilities_for_requirement(initial_requirement, graph),
296
- 0,
297
- {},
298
- []
299
- )
288
+ push_state_for_requirements(original_requested, true, graph)
300
289
  end
301
290
 
302
291
  # Unwinds the states stack because a conflict has been encountered
@@ -361,7 +350,7 @@ module Molinillo
361
350
  current_detail
362
351
  end
363
352
 
364
- # @param [Array<Object>] array of requirements that combine to create a conflict
353
+ # @param [Array<Object>] binding_requirements array of requirements that combine to create a conflict
365
354
  # @return [Array<UnwindDetails>] array of UnwindDetails that have a chance
366
355
  # of resolving the passed requirements
367
356
  def unwind_options_for_requirements(binding_requirements)
@@ -429,7 +418,7 @@ module Molinillo
429
418
  end
430
419
 
431
420
  # @param [DependencyState] state
432
- # @param [Array] array of requirements
421
+ # @param [Array] binding_requirements array of requirements
433
422
  # @return [Boolean] whether or not the given state has any possibilities
434
423
  # that could satisfy the given requirements
435
424
  def conflict_fixing_possibilities?(state, binding_requirements)
@@ -444,7 +433,8 @@ module Molinillo
444
433
 
445
434
  # Filter's a state's possibilities to remove any that would not fix the
446
435
  # conflict we've just rewound from
447
- # @param [UnwindDetails] details of the conflict just unwound from
436
+ # @param [UnwindDetails] unwind_details details of the conflict just
437
+ # unwound from
448
438
  # @return [void]
449
439
  def filter_possibilities_after_unwind(unwind_details)
450
440
  return unless state && !state.possibilities.empty?
@@ -458,14 +448,18 @@ module Molinillo
458
448
 
459
449
  # Filter's a state's possibilities to remove any that would not satisfy
460
450
  # the requirements in the conflict we've just rewound from
461
- # @param [UnwindDetails] details of the conflict just unwound from
451
+ # @param [UnwindDetails] unwind_details details of the conflict just unwound from
462
452
  # @return [void]
463
453
  def filter_possibilities_for_primary_unwind(unwind_details)
464
- all_requirements = unwind_details.conflicting_requirements
454
+ unwinds_to_state = unused_unwind_options.select { |uw| uw.state_index == unwind_details.state_index }
455
+ unwinds_to_state << unwind_details
456
+ unwind_requirement_sets = unwinds_to_state.map(&:conflicting_requirements)
465
457
 
466
458
  state.possibilities.reject! do |possibility_set|
467
459
  possibility_set.possibilities.none? do |poss|
468
- possibility_satisfies_requirements?(poss, all_requirements)
460
+ unwind_requirement_sets.any? do |requirements|
461
+ possibility_satisfies_requirements?(poss, requirements)
462
+ end
469
463
  end
470
464
  end
471
465
  end
@@ -487,7 +481,7 @@ module Molinillo
487
481
 
488
482
  # Filter's a state's possibilities to remove any that would (eventually)
489
483
  # create a requirement in the conflict we've just rewound from
490
- # @param [UnwindDetails] details of the conflict just unwound from
484
+ # @param [UnwindDetails] unwind_details details of the conflict just unwound from
491
485
  # @return [void]
492
486
  def filter_possibilities_for_parent_unwind(unwind_details)
493
487
  unwinds_to_state = unused_unwind_options.select { |uw| uw.state_index == unwind_details.state_index }
@@ -496,7 +490,7 @@ module Molinillo
496
490
  primary_unwinds = unwinds_to_state.select(&:unwinding_to_primary_requirement?).uniq
497
491
  parent_unwinds = unwinds_to_state.uniq - primary_unwinds
498
492
 
499
- allowed_possibility_sets = Compatibility.flat_map(primary_unwinds) do |unwind|
493
+ allowed_possibility_sets = primary_unwinds.flat_map do |unwind|
500
494
  states[unwind.state_index].possibilities.select do |possibility_set|
501
495
  possibility_set.possibilities.any? do |poss|
502
496
  possibility_satisfies_requirements?(poss, unwind.conflicting_requirements)
@@ -504,7 +498,7 @@ module Molinillo
504
498
  end
505
499
  end
506
500
 
507
- requirements_to_avoid = Compatibility.flat_map(parent_unwinds, &:sub_dependencies_to_avoid)
501
+ requirements_to_avoid = parent_unwinds.flat_map(&:sub_dependencies_to_avoid)
508
502
 
509
503
  state.possibilities.reject! do |possibility_set|
510
504
  !allowed_possibility_sets.include?(possibility_set) &&
@@ -520,12 +514,12 @@ module Molinillo
520
514
 
521
515
  possible_binding_requirements = conflict.requirements.values.flatten(1).uniq
522
516
 
523
- # When theres a `CircularDependency` error the conflicting requirement
524
- # (the one causing the circular) wont be `conflict.requirement`
525
- # (which wont be for the right state, because we wont have created it,
526
- # because its circular).
527
- # We need to make sure we have that requirement in the conflicts list,
528
- # otherwise we wont be able to unwind properly, so we just return all
517
+ # When there's a `CircularDependency` error the conflicting requirement
518
+ # (the one causing the circular) won't be `conflict.requirement`
519
+ # (which won't be for the right state, because we won't have created it,
520
+ # because it's circular).
521
+ # We need to make sure we have that requirement in the conflict's list,
522
+ # otherwise we won't be able to unwind properly, so we just return all
529
523
  # the requirements for the conflict.
530
524
  return possible_binding_requirements if conflict.underlying_error
531
525
 
@@ -554,8 +548,8 @@ module Molinillo
554
548
  end
555
549
 
556
550
  # @param [Object] requirement we wish to check
557
- # @param [Array] array of requirements
558
- # @param [Array] array of possibilities the requirements will be used to filter
551
+ # @param [Array] possible_binding_requirements array of requirements
552
+ # @param [Array] possibilities array of possibilities the requirements will be used to filter
559
553
  # @return [Boolean] whether or not the given requirement is required to filter
560
554
  # out all elements of the array of possibilities.
561
555
  def binding_requirement_in_set?(requirement, possible_binding_requirements, possibilities)
@@ -564,6 +558,7 @@ module Molinillo
564
558
  end
565
559
  end
566
560
 
561
+ # @param [Object] requirement
567
562
  # @return [Object] the requirement that led to `requirement` being added
568
563
  # to the list of requirements.
569
564
  def parent_of(requirement)
@@ -573,6 +568,7 @@ module Molinillo
573
568
  parent_state.requirement
574
569
  end
575
570
 
571
+ # @param [String] name
576
572
  # @return [Object] the requirement that led to a version of a possibility
577
573
  # with the given name being activated.
578
574
  def requirement_for_existing_name(name)
@@ -581,6 +577,7 @@ module Molinillo
581
577
  states.find { |s| s.name == name }.requirement
582
578
  end
583
579
 
580
+ # @param [Object] requirement
584
581
  # @return [ResolutionState] the state whose `requirement` is the given
585
582
  # `requirement`.
586
583
  def find_state_for(requirement)
@@ -588,6 +585,7 @@ module Molinillo
588
585
  states.find { |i| requirement == i.requirement }
589
586
  end
590
587
 
588
+ # @param [Object] underlying_error
591
589
  # @return [Conflict] a {Conflict} that reflects the failure to activate
592
590
  # the {#possibility} in conjunction with the current {#state}
593
591
  def create_conflict(underlying_error = nil)
@@ -624,6 +622,7 @@ module Molinillo
624
622
  vertex.requirements.map { |r| requirement_tree_for(r) }
625
623
  end
626
624
 
625
+ # @param [Object] requirement
627
626
  # @return [Array<Object>] the list of requirements that led to
628
627
  # `requirement` being required.
629
628
  def requirement_tree_for(requirement)
@@ -669,9 +668,8 @@ module Molinillo
669
668
  attempt_to_filter_existing_spec(existing_vertex)
670
669
  else
671
670
  latest = possibility.latest_version
672
- # use reject!(!satisfied) for 1.8.7 compatibility
673
- possibility.possibilities.reject! do |possibility|
674
- !requirement_satisfied_by?(requirement, activated, possibility)
671
+ possibility.possibilities.select! do |possibility|
672
+ requirement_satisfied_by?(requirement, activated, possibility)
675
673
  end
676
674
  if possibility.latest_version.nil?
677
675
  # ensure there's a possibility for better error messages
@@ -701,7 +699,7 @@ module Molinillo
701
699
 
702
700
  # Generates a filtered version of the existing vertex's `PossibilitySet` using the
703
701
  # current state's `requirement`
704
- # @param [Object] existing vertex
702
+ # @param [Object] vertex existing vertex
705
703
  # @return [PossibilitySet] filtered possibility set
706
704
  def filtered_possibility_set(vertex)
707
705
  PossibilitySet.new(vertex.payload.dependencies, vertex.payload.possibilities & possibility.possibilities)
@@ -726,7 +724,7 @@ module Molinillo
726
724
  end
727
725
 
728
726
  # Requires the dependencies that the recently activated spec has
729
- # @param [Object] activated_possibility the PossibilitySet that has just been
727
+ # @param [Object] possibility_set the PossibilitySet that has just been
730
728
  # activated
731
729
  # @return [void]
732
730
  def require_nested_dependencies_for(possibility_set)
@@ -745,6 +743,8 @@ module Molinillo
745
743
  # Pushes a new {DependencyState} that encapsulates both existing and new
746
744
  # requirements
747
745
  # @param [Array] new_requirements
746
+ # @param [Boolean] requires_sort
747
+ # @param [Object] new_activated
748
748
  # @return [void]
749
749
  def push_state_for_requirements(new_requirements, requires_sort = true, new_activated = activated)
750
750
  new_requirements = sort_dependencies(new_requirements.uniq, new_activated, conflicts) if requires_sort
@@ -763,7 +763,8 @@ module Molinillo
763
763
 
764
764
  # Checks a proposed requirement with any existing locked requirement
765
765
  # before generating an array of possibilities for it.
766
- # @param [Object] the proposed requirement
766
+ # @param [Object] requirement the proposed requirement
767
+ # @param [Object] activated
767
768
  # @return [Array] possibilities
768
769
  def possibilities_for_requirement(requirement, activated = self.activated)
769
770
  return [] unless requirement
@@ -774,7 +775,8 @@ module Molinillo
774
775
  group_possibilities(search_for(requirement))
775
776
  end
776
777
 
777
- # @param [Object] the proposed requirement
778
+ # @param [Object] requirement the proposed requirement
779
+ # @param [Object] activated
778
780
  # @return [Array] possibility set containing only the locked requirement, if any
779
781
  def locked_requirement_possibility_set(requirement, activated = self.activated)
780
782
  all_possibilities = search_for(requirement)
@@ -793,8 +795,8 @@ module Molinillo
793
795
  # Build an array of PossibilitySets, with each element representing a group of
794
796
  # dependency versions that all have the same sub-dependency version constraints
795
797
  # and are contiguous.
796
- # @param [Array] an array of possibilities
797
- # @return [Array] an array of possibility sets
798
+ # @param [Array] possibilities an array of possibilities
799
+ # @return [Array<PossibilitySet>] an array of possibility sets
798
800
  def group_possibilities(possibilities)
799
801
  possibility_sets = []
800
802
  current_possibility_set = nil
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'molinillo/dependency_graph'
3
+ require_relative 'dependency_graph'
4
4
 
5
5
  module Molinillo
6
6
  # This class encapsulates a dependency resolver.
@@ -9,7 +9,7 @@ module Molinillo
9
9
  #
10
10
  #
11
11
  class Resolver
12
- require 'molinillo/resolution'
12
+ require_relative 'resolution'
13
13
 
14
14
  # @return [SpecificationProvider] the specification provider used
15
15
  # in the resolution process
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: molinillo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel E. Giddins
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-25 00:00:00.000000000 Z
11
+ date: 2020-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,7 +38,7 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- description:
41
+ description:
42
42
  email:
43
43
  - segiddins@segiddins.me
44
44
  executables: []
@@ -50,7 +50,6 @@ files:
50
50
  - LICENSE
51
51
  - README.md
52
52
  - lib/molinillo.rb
53
- - lib/molinillo/compatibility.rb
54
53
  - lib/molinillo/delegates/resolution_state.rb
55
54
  - lib/molinillo/delegates/specification_provider.rb
56
55
  - lib/molinillo/dependency_graph.rb
@@ -74,7 +73,7 @@ homepage: https://github.com/CocoaPods/Molinillo
74
73
  licenses:
75
74
  - MIT
76
75
  metadata: {}
77
- post_install_message:
76
+ post_install_message:
78
77
  rdoc_options: []
79
78
  require_paths:
80
79
  - lib
@@ -82,17 +81,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
82
81
  requirements:
83
82
  - - ">="
84
83
  - !ruby/object:Gem::Version
85
- version: '0'
84
+ version: 2.0.0
86
85
  required_rubygems_version: !ruby/object:Gem::Requirement
87
86
  requirements:
88
87
  - - ">="
89
88
  - !ruby/object:Gem::Version
90
89
  version: '0'
91
90
  requirements: []
92
- rubyforge_project:
93
- rubygems_version: 2.6.12
94
- signing_key:
91
+ rubygems_version: 3.1.3
92
+ signing_key:
95
93
  specification_version: 4
96
94
  summary: Provides support for dependency resolution
97
95
  test_files: []
98
- has_rdoc:
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Molinillo
4
- # Hacks needed for old Ruby versions.
5
- module Compatibility
6
- module_function
7
-
8
- if [].respond_to?(:flat_map)
9
- # Flat map
10
- # @param [Enumerable] enum an enumerable object
11
- # @block the block to flat-map with
12
- # @return The enum, flat-mapped
13
- def flat_map(enum, &blk)
14
- enum.flat_map(&blk)
15
- end
16
- else
17
- # Flat map
18
- # @param [Enumerable] enum an enumerable object
19
- # @block the block to flat-map with
20
- # @return The enum, flat-mapped
21
- def flat_map(enum, &blk)
22
- enum.map(&blk).flatten(1)
23
- end
24
- end
25
- end
26
- end