summaryrefslogtreecommitdiff
path: root/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb')
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb28
1 files changed, 16 insertions, 12 deletions
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb
index 712864495f..cc572b411a 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb
@@ -12,13 +12,15 @@ module Gem::Resolver::Molinillo
# @attr [Object] locked_requirement the relevant locking requirement.
# @attr [Array<Array<Object>>] requirement_trees the different requirement
# trees that led to every requirement for the conflicting name.
+ # @attr [{String=>Object}] activated_by_name the already-activated specs.
Conflict = Struct.new(
:requirement,
:requirements,
:existing,
:possibility,
:locked_requirement,
- :requirement_trees
+ :requirement_trees,
+ :activated_by_name
)
# @return [SpecificationProvider] the provider that knows about
@@ -164,7 +166,7 @@ module Gem::Resolver::Molinillo
# @return [DependencyState] the initial state for the resolution
def initial_state
graph = DependencyGraph.new.tap do |dg|
- original_requested.each { |r| dg.add_root_vertex(name_for(r), nil).tap { |v| v.explicit_requirements << r } }
+ original_requested.each { |r| dg.add_vertex(name_for(r), nil, true).tap { |v| v.explicit_requirements << r } }
end
requirements = sort_dependencies(original_requested, graph, {})
@@ -216,7 +218,7 @@ module Gem::Resolver::Molinillo
return nil unless requirement
seen = false
state = states.reverse_each.find do |s|
- seen ||= s.requirement == requirement
+ seen ||= s.requirement == requirement || s.requirements.include?(requirement)
seen && s.requirement != requirement && !s.requirements.include?(requirement)
end
state && state.requirement
@@ -250,21 +252,23 @@ module Gem::Resolver::Molinillo
name_for_explicit_dependency_source => vertex.explicit_requirements,
name_for_locking_dependency_source => Array(locked_requirement_named(name)),
}
- vertex.incoming_edges.each { |edge| (requirements[edge.origin.payload] ||= []).unshift(*edge.requirements) }
+ vertex.incoming_edges.each { |edge| (requirements[edge.origin.payload] ||= []).unshift(edge.requirement) }
conflicts[name] = Conflict.new(
requirement,
Hash[requirements.select { |_, r| !r.empty? }],
vertex.payload,
possibility,
locked_requirement_named(name),
- requirement_trees
+ requirement_trees,
+ Hash[activated.map { |v| [v.name, v.payload] }.select(&:last)]
)
end
# @return [Array<Array<Object>>] The different requirement
# trees that led to every requirement for the current spec.
def requirement_trees
- activated.vertex_named(name).requirements.map { |r| requirement_tree_for(r) }
+ vertex = activated.vertex_named(name)
+ vertex.requirements.map { |r| requirement_tree_for(r) }
end
# @return [Array<Object>] the list of requirements that led to
@@ -322,7 +326,7 @@ module Gem::Resolver::Molinillo
existing_spec = existing_node.payload
if requirement_satisfied_by?(requirement, activated, existing_spec)
new_requirements = requirements.dup
- push_state_for_requirements(new_requirements)
+ push_state_for_requirements(new_requirements, false)
else
return if attempt_to_swap_possibility
create_conflict
@@ -389,17 +393,17 @@ module Gem::Resolver::Molinillo
def require_nested_dependencies_for(activated_spec)
nested_dependencies = dependencies_for(activated_spec)
debug(depth) { "Requiring nested dependencies (#{nested_dependencies.map(&:to_s).join(', ')})" }
- nested_dependencies.each { |d| activated.add_child_vertex name_for(d), nil, [name_for(activated_spec)], d }
+ nested_dependencies.each { |d| activated.add_child_vertex(name_for(d), nil, [name_for(activated_spec)], d) }
- push_state_for_requirements(requirements + nested_dependencies)
+ push_state_for_requirements(requirements + nested_dependencies, nested_dependencies.size > 0)
end
# Pushes a new {DependencyState} that encapsulates both existing and new
# requirements
# @param [Array] new_requirements
# @return [void]
- def push_state_for_requirements(new_requirements, new_activated = activated.dup)
- new_requirements = sort_dependencies(new_requirements.uniq, new_activated, conflicts)
+ def push_state_for_requirements(new_requirements, requires_sort = true, new_activated = activated.dup)
+ new_requirements = sort_dependencies(new_requirements.uniq, new_activated, conflicts) if requires_sort
new_requirement = new_requirements.shift
new_name = new_requirement ? name_for(new_requirement) : ''
possibilities = new_requirement ? search_for(new_requirement) : []
@@ -420,7 +424,7 @@ module Gem::Resolver::Molinillo
def handle_missing_or_push_dependency_state(state)
if state.requirement && state.possibilities.empty? && allow_missing?(state.requirement)
state.activated.detach_vertex_named(state.name)
- push_state_for_requirements(state.requirements, state.activated)
+ push_state_for_requirements(state.requirements.dup, false, state.activated)
else
states.push state
end