def resolve(reqs, activated)
throw :success, successify(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 : @gems_size[a] ]
end
debug { "Activated:\n" + activated.values.map {|a| " #{a}" }.join("\n") }
debug { "Requirements:\n" + reqs.map {|r| " #{r}"}.join("\n") }
activated = activated.dup
current = reqs.shift
debug { "Attempting:\n #{current}"}
existing = activated[current.name]
if existing || current.name == 'bundler'
if current.name == 'bundler' && !existing
existing = search(DepProxy.new(Gem::Dependency.new('bundler', VERSION), Gem::Platform::RUBY)).first
raise GemNotFound, %Q{Bundler could not find gem "bundler" (#{VERSION})} unless existing
existing.required_by << existing
activated['bundler'] = existing
end
if current.requirement.satisfied_by?(existing.version)
debug { " * [SUCCESS] Already activated" }
@errors.delete(existing.name)
dependencies = existing.activate_platform(current.__platform)
reqs.concat dependencies
dependencies.each do |dep|
next if dep.type == :development
@gems_size[dep] ||= gems_size(dep)
end
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
parent ||= existing.required_by.last if existing.respond_to?(:required_by)
if parent && parent.name != 'bundler'
debug { " -> Jumping to: #{parent.name}" }
required_by = existing.respond_to?(:required_by) && existing.required_by.last
throw parent.name, required_by && required_by.name
else
raise version_conflict
end
end
else
conflicts = Set.new
matching_versions = search(current)
if matching_versions.empty?
if current.required_by.empty?
if base = @base[current.name] and !base.empty?
version = base.first.version
message = "You have requested:\n" \
" #{current.name} #{current.requirement}\n\n" \
"The bundle currently has #{current.name} locked at #{version}.\n" \
"Try running `bundle update #{current.name}`"
elsif 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.source_types.include?(Bundler::Source::Rubygems)
message << "in any of the gem sources listed in your Gemfile."
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_group|
conflict = resolve_requirement(spec_group, 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