Skip to content

Commit

Permalink
Merge pull request #3402 from rubygems/molinillos_master
Browse files Browse the repository at this point in the history
Bump vendored molinillo of bundler to 0.7.0

(cherry picked from commit 0012d77)
  • Loading branch information
deivid-rodriguez committed Dec 7, 2020
1 parent 7a22cbf commit b668262
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 73 deletions.
1 change: 0 additions & 1 deletion Manifest.txt
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb
bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb
bundler/lib/bundler/vendor/fileutils/lib/fileutils.rb
bundler/lib/bundler/vendor/molinillo/lib/molinillo.rb
bundler/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb
bundler/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb
bundler/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb
bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb
Expand Down
1 change: 1 addition & 0 deletions bundler/Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ load "task/automatiek.rake"

desc "Vendor a specific version of molinillo"
Automatiek::RakeTask.new("molinillo") do |lib|
lib.version = "0.7.0"
lib.download = { :github => "https://github.com/CocoaPods/Molinillo" }
lib.namespace = "Molinillo"
lib.prefix = "Bundler"
Expand Down
1 change: 0 additions & 1 deletion bundler/lib/bundler/vendor/molinillo/lib/molinillo.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# frozen_string_literal: true

require_relative 'molinillo/compatibility'
require_relative 'molinillo/gem_metadata'
require_relative 'molinillo/errors'
require_relative 'molinillo/resolver'
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ def to_dot(options = {})
dot.join("\n")
end

# @param [DependencyGraph] other
# @return [Boolean] whether the two dependency graphs are equal, determined
# by a recursive traversal of each {#root_vertices} and its
# {Vertex#successors}
Expand Down Expand Up @@ -190,7 +191,7 @@ def root_vertex_named(name)
# @return [Edge] the added edge
def add_edge(origin, destination, requirement)
if destination.path_to?(origin)
raise CircularDependencyError.new([origin, destination])
raise CircularDependencyError.new(path(destination, origin))
end
add_edge_no_circular(origin, destination, requirement)
end
Expand Down Expand Up @@ -219,5 +220,37 @@ def set_payload(name, payload)
def add_edge_no_circular(origin, destination, requirement)
log.add_edge_no_circular(self, origin.name, destination.name, requirement)
end

# Returns the path between two vertices
# @raise [ArgumentError] if there is no path between the vertices
# @param [Vertex] from
# @param [Vertex] to
# @return [Array<Vertex>] the shortest path from `from` to `to`
def path(from, to)
distances = Hash.new(vertices.size + 1)
distances[from.name] = 0
predecessors = {}
each do |vertex|
vertex.successors.each do |successor|
if distances[successor.name] > distances[vertex.name] + 1
distances[successor.name] = distances[vertex.name] + 1
predecessors[successor] = vertex
end
end
end

path = [to]
while before = predecessors[to]
path << before
to = before
break if to == from
end

unless path.last.equal?(from)
raise ArgumentError, "There is no path from #{from.name} to #{to.name}"
end

path.reverse
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ def self.action_name
end

# (see Action#up)
def up(_graph)
def up(graph)
end

# (see Action#down)
def down(_graph)
def down(graph)
end

# @!group Tag
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class VersionConflict < ResolverError
# @param [SpecificationProvider] specification_provider see {#specification_provider}
def initialize(conflicts, specification_provider)
pairs = []
Compatibility.flat_map(conflicts.values.flatten, &:requirements).each do |conflicting|
conflicts.values.flat_map(&:requirements).each do |conflicting|
conflicting.each do |source, conflict_requirements|
conflict_requirements.each do |c|
pairs << [c, source]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

module Bundler::Molinillo
# The version of Bundler::Molinillo.
VERSION = '0.6.6'.freeze
VERSION = '0.7.0'.freeze
end
78 changes: 38 additions & 40 deletions bundler/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def resolve
def start_resolution
@started_at = Time.now

handle_missing_or_push_dependency_state(initial_state)
push_initial_state

debug { "Starting resolution (#{@started_at})\nUser-requested dependencies: #{original_requested}" }
resolver_ui.before_resolution
Expand Down Expand Up @@ -273,10 +273,10 @@ def state
states.last
end

# Creates the initial state for the resolution, based upon the
# Creates and pushes the initial state for the resolution, based upon the
# {#requested} dependencies
# @return [DependencyState] the initial state for the resolution
def initial_state
# @return [void]
def push_initial_state
graph = DependencyGraph.new.tap do |dg|
original_requested.each do |requested|
vertex = dg.add_vertex(name_for(requested), nil, true)
Expand All @@ -285,18 +285,7 @@ def initial_state
dg.tag(:initial_state)
end

requirements = sort_dependencies(original_requested, graph, {})
initial_requirement = requirements.shift
DependencyState.new(
initial_requirement && name_for(initial_requirement),
requirements,
graph,
initial_requirement,
possibilities_for_requirement(initial_requirement, graph),
0,
{},
[]
)
push_state_for_requirements(original_requested, true, graph)
end

# Unwinds the states stack because a conflict has been encountered
Expand Down Expand Up @@ -361,7 +350,7 @@ def build_details_for_unwind
current_detail
end

# @param [Array<Object>] array of requirements that combine to create a conflict
# @param [Array<Object>] binding_requirements array of requirements that combine to create a conflict
# @return [Array<UnwindDetails>] array of UnwindDetails that have a chance
# of resolving the passed requirements
def unwind_options_for_requirements(binding_requirements)
Expand Down Expand Up @@ -429,7 +418,7 @@ def unwind_options_for_requirements(binding_requirements)
end

# @param [DependencyState] state
# @param [Array] array of requirements
# @param [Array] binding_requirements array of requirements
# @return [Boolean] whether or not the given state has any possibilities
# that could satisfy the given requirements
def conflict_fixing_possibilities?(state, binding_requirements)
Expand All @@ -444,7 +433,8 @@ def conflict_fixing_possibilities?(state, binding_requirements)

# Filter's a state's possibilities to remove any that would not fix the
# conflict we've just rewound from
# @param [UnwindDetails] details of the conflict just unwound from
# @param [UnwindDetails] unwind_details details of the conflict just
# unwound from
# @return [void]
def filter_possibilities_after_unwind(unwind_details)
return unless state && !state.possibilities.empty?
Expand All @@ -458,7 +448,7 @@ def filter_possibilities_after_unwind(unwind_details)

# Filter's a state's possibilities to remove any that would not satisfy
# the requirements in the conflict we've just rewound from
# @param [UnwindDetails] details of the conflict just unwound from
# @param [UnwindDetails] unwind_details details of the conflict just unwound from
# @return [void]
def filter_possibilities_for_primary_unwind(unwind_details)
unwinds_to_state = unused_unwind_options.select { |uw| uw.state_index == unwind_details.state_index }
Expand Down Expand Up @@ -491,7 +481,7 @@ def possibility_satisfies_requirements?(possibility, requirements)

# Filter's a state's possibilities to remove any that would (eventually)
# create a requirement in the conflict we've just rewound from
# @param [UnwindDetails] details of the conflict just unwound from
# @param [UnwindDetails] unwind_details details of the conflict just unwound from
# @return [void]
def filter_possibilities_for_parent_unwind(unwind_details)
unwinds_to_state = unused_unwind_options.select { |uw| uw.state_index == unwind_details.state_index }
Expand All @@ -500,15 +490,15 @@ def filter_possibilities_for_parent_unwind(unwind_details)
primary_unwinds = unwinds_to_state.select(&:unwinding_to_primary_requirement?).uniq
parent_unwinds = unwinds_to_state.uniq - primary_unwinds

allowed_possibility_sets = Compatibility.flat_map(primary_unwinds) do |unwind|
allowed_possibility_sets = primary_unwinds.flat_map do |unwind|
states[unwind.state_index].possibilities.select do |possibility_set|
possibility_set.possibilities.any? do |poss|
possibility_satisfies_requirements?(poss, unwind.conflicting_requirements)
end
end
end

requirements_to_avoid = Compatibility.flat_map(parent_unwinds, &:sub_dependencies_to_avoid)
requirements_to_avoid = parent_unwinds.flat_map(&:sub_dependencies_to_avoid)

state.possibilities.reject! do |possibility_set|
!allowed_possibility_sets.include?(possibility_set) &&
Expand All @@ -524,12 +514,12 @@ def binding_requirements_for_conflict(conflict)

possible_binding_requirements = conflict.requirements.values.flatten(1).uniq

# When theres a `CircularDependency` error the conflicting requirement
# (the one causing the circular) wont be `conflict.requirement`
# (which wont be for the right state, because we wont have created it,
# because its circular).
# We need to make sure we have that requirement in the conflicts list,
# otherwise we wont be able to unwind properly, so we just return all
# When there's a `CircularDependency` error the conflicting requirement
# (the one causing the circular) won't be `conflict.requirement`
# (which won't be for the right state, because we won't have created it,
# because it's circular).
# We need to make sure we have that requirement in the conflict's list,
# otherwise we won't be able to unwind properly, so we just return all
# the requirements for the conflict.
return possible_binding_requirements if conflict.underlying_error

Expand Down Expand Up @@ -558,8 +548,8 @@ def binding_requirements_for_conflict(conflict)
end

# @param [Object] requirement we wish to check
# @param [Array] array of requirements
# @param [Array] array of possibilities the requirements will be used to filter
# @param [Array] possible_binding_requirements array of requirements
# @param [Array] possibilities array of possibilities the requirements will be used to filter
# @return [Boolean] whether or not the given requirement is required to filter
# out all elements of the array of possibilities.
def binding_requirement_in_set?(requirement, possible_binding_requirements, possibilities)
Expand All @@ -568,6 +558,7 @@ def binding_requirement_in_set?(requirement, possible_binding_requirements, poss
end
end

# @param [Object] requirement
# @return [Object] the requirement that led to `requirement` being added
# to the list of requirements.
def parent_of(requirement)
Expand All @@ -577,6 +568,7 @@ def parent_of(requirement)
parent_state.requirement
end

# @param [String] name
# @return [Object] the requirement that led to a version of a possibility
# with the given name being activated.
def requirement_for_existing_name(name)
Expand All @@ -585,13 +577,15 @@ def requirement_for_existing_name(name)
states.find { |s| s.name == name }.requirement
end

# @param [Object] requirement
# @return [ResolutionState] the state whose `requirement` is the given
# `requirement`.
def find_state_for(requirement)
return nil unless requirement
states.find { |i| requirement == i.requirement }
end

# @param [Object] underlying_error
# @return [Conflict] a {Conflict} that reflects the failure to activate
# the {#possibility} in conjunction with the current {#state}
def create_conflict(underlying_error = nil)
Expand Down Expand Up @@ -628,6 +622,7 @@ def requirement_trees
vertex.requirements.map { |r| requirement_tree_for(r) }
end

# @param [Object] requirement
# @return [Array<Object>] the list of requirements that led to
# `requirement` being required.
def requirement_tree_for(requirement)
Expand Down Expand Up @@ -673,9 +668,8 @@ def attempt_to_activate
attempt_to_filter_existing_spec(existing_vertex)
else
latest = possibility.latest_version
# use reject!(!satisfied) for 1.8.7 compatibility
possibility.possibilities.reject! do |possibility|
!requirement_satisfied_by?(requirement, activated, possibility)
possibility.possibilities.select! do |possibility|
requirement_satisfied_by?(requirement, activated, possibility)
end
if possibility.latest_version.nil?
# ensure there's a possibility for better error messages
Expand Down Expand Up @@ -705,7 +699,7 @@ def attempt_to_filter_existing_spec(vertex)

# Generates a filtered version of the existing vertex's `PossibilitySet` using the
# current state's `requirement`
# @param [Object] existing vertex
# @param [Object] vertex existing vertex
# @return [PossibilitySet] filtered possibility set
def filtered_possibility_set(vertex)
PossibilitySet.new(vertex.payload.dependencies, vertex.payload.possibilities & possibility.possibilities)
Expand All @@ -730,7 +724,7 @@ def activate_new_spec
end

# Requires the dependencies that the recently activated spec has
# @param [Object] activated_possibility the PossibilitySet that has just been
# @param [Object] possibility_set the PossibilitySet that has just been
# activated
# @return [void]
def require_nested_dependencies_for(possibility_set)
Expand All @@ -749,6 +743,8 @@ def require_nested_dependencies_for(possibility_set)
# Pushes a new {DependencyState} that encapsulates both existing and new
# requirements
# @param [Array] new_requirements
# @param [Boolean] requires_sort
# @param [Object] new_activated
# @return [void]
def push_state_for_requirements(new_requirements, requires_sort = true, new_activated = activated)
new_requirements = sort_dependencies(new_requirements.uniq, new_activated, conflicts) if requires_sort
Expand All @@ -767,7 +763,8 @@ def push_state_for_requirements(new_requirements, requires_sort = true, new_acti

# Checks a proposed requirement with any existing locked requirement
# before generating an array of possibilities for it.
# @param [Object] the proposed requirement
# @param [Object] requirement the proposed requirement
# @param [Object] activated
# @return [Array] possibilities
def possibilities_for_requirement(requirement, activated = self.activated)
return [] unless requirement
Expand All @@ -778,7 +775,8 @@ def possibilities_for_requirement(requirement, activated = self.activated)
group_possibilities(search_for(requirement))
end

# @param [Object] the proposed requirement
# @param [Object] requirement the proposed requirement
# @param [Object] activated
# @return [Array] possibility set containing only the locked requirement, if any
def locked_requirement_possibility_set(requirement, activated = self.activated)
all_possibilities = search_for(requirement)
Expand All @@ -797,8 +795,8 @@ def locked_requirement_possibility_set(requirement, activated = self.activated)
# Build an array of PossibilitySets, with each element representing a group of
# dependency versions that all have the same sub-dependency version constraints
# and are contiguous.
# @param [Array] an array of possibilities
# @return [Array] an array of possibility sets
# @param [Array] possibilities an array of possibilities
# @return [Array<PossibilitySet>] an array of possibility sets
def group_possibilities(possibilities)
possibility_sets = []
current_possibility_set = nil
Expand Down

0 comments on commit b668262

Please sign in to comment.