Class | Gem::DependencyList |
In: |
lib/rubygems/dependency_list.rb
|
Parent: | Object |
Gem::DependencyList is used for installing and uninstalling gems in the correct order to avoid conflicts.
development | [RW] | Allows enabling/disabling use of development dependencies |
specs | [R] |
Creates a DependencyList from a Gem::SourceIndex source_index
# File lib/rubygems/dependency_list.rb, line 27 27: def self.from_source_index(source_index) 28: list = new 29: 30: source_index.each do |full_name, spec| 31: list.add spec 32: end 33: 34: list 35: end
Creates a new DependencyList. If development is true, development dependencies will be included.
# File lib/rubygems/dependency_list.rb, line 41 41: def initialize development = false 42: @specs = [] 43: 44: @development = development 45: end
Adds gemspecs to the dependency list.
# File lib/rubygems/dependency_list.rb, line 50 50: def add(*gemspecs) 51: @specs.push(*gemspecs) 52: end
Return a list of the gem specifications in the dependency list, sorted in order so that no gemspec in the list depends on a gemspec earlier in the list.
This is useful when removing gems from a set of installed gems. By removing them in the returned order, you don‘t get into as many dependency issues.
If there are circular dependencies (yuck!), then gems will be returned in order until only the circular dependents and anything they reference are left. Then arbitrary gemspecs will be returned until the circular dependency is broken, after which gems will be returned in dependency order again.
# File lib/rubygems/dependency_list.rb, line 73 73: def dependency_order 74: sorted = strongly_connected_components.flatten 75: 76: result = [] 77: seen = {} 78: 79: sorted.each do |spec| 80: if index = seen[spec.name] then 81: if result[index].version < spec.version then 82: result[index] = spec 83: end 84: else 85: seen[spec.name] = result.length 86: result << spec 87: end 88: end 89: 90: result.reverse 91: end
Iterator over dependency_order
# File lib/rubygems/dependency_list.rb, line 96 96: def each(&block) 97: dependency_order.each(&block) 98: end
# File lib/rubygems/dependency_list.rb, line 100 100: def find_name(full_name) 101: @specs.find { |spec| spec.full_name == full_name } 102: end
Are all the dependencies in the list satisfied?
# File lib/rubygems/dependency_list.rb, line 111 111: def ok? 112: why_not_ok?(:quick).empty? 113: end
Is is ok to remove a gemspec from the dependency list?
If removing the gemspec creates breaks a currently ok dependency, then it is NOT ok to remove the gemspec.
# File lib/rubygems/dependency_list.rb, line 140 140: def ok_to_remove?(full_name) 141: gem_to_remove = find_name full_name 142: 143: siblings = @specs.find_all { |s| 144: s.name == gem_to_remove.name && 145: s.full_name != gem_to_remove.full_name 146: } 147: 148: deps = [] 149: 150: @specs.each do |spec| 151: spec.dependencies.each do |dep| 152: deps << dep if gem_to_remove.satisfies_requirement?(dep) 153: end 154: end 155: 156: deps.all? { |dep| 157: siblings.any? { |s| 158: s.satisfies_requirement? dep 159: } 160: } 161: end
Removes the gemspec matching full_name from the dependency list
# File lib/rubygems/dependency_list.rb, line 178 178: def remove_by_name(full_name) 179: @specs.delete_if { |spec| spec.full_name == full_name } 180: end
Remove everything in the DependencyList that matches but doesn‘t satisfy items in dependencies (a hash of gem names to arrays of dependencies).
# File lib/rubygems/dependency_list.rb, line 168 168: def remove_specs_unsatisfied_by dependencies 169: specs.reject! { |spec| 170: dep = dependencies[spec.name] 171: dep and not dep.requirement.satisfied_by? spec.version 172: } 173: end
Return a hash of predecessors. result[spec] is an Array of gemspecs that have a dependency satisfied by the named gemspec.
# File lib/rubygems/dependency_list.rb, line 186 186: def spec_predecessors 187: result = Hash.new { |h,k| h[k] = [] } 188: 189: specs = @specs.sort.reverse 190: 191: specs.each do |spec| 192: specs.each do |other| 193: next if spec == other 194: 195: other.dependencies.each do |dep| 196: if spec.satisfies_requirement? dep then 197: result[spec] << other 198: end 199: end 200: end 201: end 202: 203: result 204: end
# File lib/rubygems/dependency_list.rb, line 210 210: def tsort_each_child(node, &block) 211: specs = @specs.sort.reverse 212: 213: dependencies = node.runtime_dependencies 214: dependencies.push(*node.development_dependencies) if @development 215: 216: dependencies.each do |dep| 217: specs.each do |spec| 218: if spec.satisfies_requirement? dep then 219: begin 220: yield spec 221: rescue TSort::Cyclic 222: # do nothing 223: end 224: break 225: end 226: end 227: end 228: end
# File lib/rubygems/dependency_list.rb, line 206 206: def tsort_each_node(&block) 207: @specs.each(&block) 208: end
# File lib/rubygems/dependency_list.rb, line 115 115: def why_not_ok? quick = false 116: unsatisfied = Hash.new { |h,k| h[k] = [] } 117: source_index = Gem.source_index 118: each do |spec| 119: spec.runtime_dependencies.each do |dep| 120: inst = source_index.any? { |_, installed_spec| 121: dep.name == installed_spec.name and 122: dep.requirement.satisfied_by? installed_spec.version 123: } 124: 125: unless inst or @specs.find { |s| s.satisfies_requirement? dep } then 126: unsatisfied[spec.name] << dep 127: return unsatisfied if quick 128: end 129: end 130: end 131: unsatisfied 132: end