2 # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
4 # See LICENSE.txt for permissions.
9 class Gem::DependencyList
13 def self.from_source_index(src_index)
16 src_index.each do |full_name, spec|
27 # Adds +gemspecs+ to the dependency list.
29 @specs.push(*gemspecs)
32 # Return a list of the specifications in the dependency list,
33 # sorted in order so that no spec in the list depends on a gem
34 # earlier in the list.
36 # This is useful when removing gems from a set of installed gems.
37 # By removing them in the returned order, you don't get into as
38 # many dependency issues.
40 # If there are circular dependencies (yuck!), then gems will be
41 # returned in order until only the circular dependents and anything
42 # they reference are left. Then arbitrary gemspecs will be returned
43 # until the circular dependency is broken, after which gems will be
44 # returned in dependency order again.
46 sorted = strongly_connected_components.flatten
52 if index = seen[spec.name] then
53 if result[index].version < spec.version then
57 seen[spec.name] = result.length
65 def find_name(full_name)
66 @specs.find { |spec| spec.full_name == full_name }
69 # Are all the dependencies in the list satisfied?
72 spec.runtime_dependencies.all? do |dep|
73 @specs.find { |s| s.satisfies_requirement? dep }
78 # Is is ok to remove a gem from the dependency list?
80 # If removing the gemspec creates breaks a currently ok dependency,
81 # then it is NOT ok to remove the gem.
82 def ok_to_remove?(full_name)
83 gem_to_remove = find_name full_name
85 siblings = @specs.find_all { |s|
86 s.name == gem_to_remove.name &&
87 s.full_name != gem_to_remove.full_name
93 spec.dependencies.each do |dep|
94 deps << dep if gem_to_remove.satisfies_requirement?(dep)
100 s.satisfies_requirement? dep
105 def remove_by_name(full_name)
106 @specs.delete_if { |spec| spec.full_name == full_name }
109 # Return a hash of predecessors. <tt>result[spec]</tt> is an
110 # Array of gemspecs that have a dependency satisfied by the named
112 def spec_predecessors
113 result = Hash.new { |h,k| h[k] = [] }
115 specs = @specs.sort.reverse
118 specs.each do |other|
119 next if spec == other
121 other.dependencies.each do |dep|
122 if spec.satisfies_requirement? dep then
123 result[spec] << other
132 def tsort_each_node(&block)
136 def tsort_each_child(node, &block)
137 specs = @specs.sort.reverse
139 node.dependencies.each do |dep|
141 if spec.satisfies_requirement? dep then
154 # Count the number of gemspecs in the list +specs+ that are not in
156 def active_count(specs, ignored)
159 result += 1 unless ignored[spec.full_name]