def resolve(reqs, activated)
throw :success, activated if reqs.empty?
debug { print "\e[2J\e[f" ; "==== Iterating ====\n\n" }
reqs = reqs.sort_by do |a|
[ activated[a.name] ? 0 : 1,
a.requirement.prerelease? ? 0 : 1,
@errors[a.name] ? 0 : 1,
activated[a.name] ? 0 : search(a).size ]
end
debug { "Activated:\n" + activated.values.map { |a| " #{a.name} (#{a.version})" }.join("\n") }
debug { "Requirements:\n" + reqs.map { |r| " #{r.name} (#{r.requirement})"}.join("\n") }
activated = activated.dup
if reqs.first.name == "bundler" && !activated["bundler"]
bundler_version = ENV["BUNDLER_VERSION"] || Bundler::VERSION
current = Gem::Dependency.new("bundler", bundler_version, reqs.first.type)
else
current = reqs.shift
end
debug { "Attempting:\n #{current.name} (#{current.requirement})"}
if existing = activated[current.name]
if current.requirement.satisfied_by?(existing.version)
debug { " * [SUCCESS] Already activated" }
@errors.delete(existing.name)
resolve(reqs, activated)
else
debug { " * [FAIL] Already activated" }
@errors[existing.name] = [existing, current]
debug { current.required_by.map {|d| " * #{d.name} (#{d.requirement})" }.join("\n") }
parent = current.required_by.last || existing.required_by.last
debug { " -> Jumping to: #{parent.name}" }
throw parent.name, existing.required_by.last.name
end
else
conflicts = Set.new
matching_versions = search(current)
if matching_versions.empty?
if current.required_by.empty?
if current.source
name = current.name
versions = @source_requirements[name][name].map { |s| s.version }
message = "Could not find gem '#{current}' in #{current.source}.\n"
if versions.any?
message << "Source contains '#{name}' at: #{versions.join(', ')}"
else
message << "Source does not contain any versions of '#{current}'"
end
else
message = "Could not find gem '#{current}' "
if @index.sources.include?(Bundler::Source::Rubygems)
message << "in any of the gem sources."
else
message << "in the gems available on this machine."
end
end
raise GemNotFound, message
else
@errors[current.name] = [nil, current]
end
end
matching_versions.reverse_each do |spec|
conflict = resolve_requirement(spec, current, reqs.dup, activated.dup)
conflicts << conflict if conflict
end
if current.required_by.empty? && !conflicts.empty?
@stack.reverse_each do |savepoint|
if conflicts.include?(savepoint)
debug { " -> Jumping to: #{savepoint}" }
throw savepoint
end
end
end
end
end