Class: Gem::DependencyList
- Inherits:
-
Object
- Object
- Gem::DependencyList
- Includes:
- Enumerable, TSort
- Defined in:
- lib/rubygems/dependency_list.rb
Overview
Gem::DependencyList is used for installing and uninstalling gems in the correct order to avoid conflicts. – TODO: It appears that all but topo-sort functionality is being duplicated (or is planned to be duplicated) elsewhere in rubygems. Is the majority of this class necessary anymore? Especially #ok?, #why_not_ok?
Instance Attribute Summary collapse
-
#development ⇒ Object
Allows enabling/disabling use of development dependencies.
-
#specs ⇒ Object
readonly
Returns the value of attribute specs.
Class Method Summary collapse
-
.from_specs ⇒ Object
Creates a DependencyList from the current specs.
Instance Method Summary collapse
-
#add(*gemspecs) ⇒ Object
Adds
gemspecs
to the dependency list. - #clear ⇒ Object
-
#dependency_order ⇒ Object
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.
-
#each(&block) ⇒ Object
Iterator over dependency_order.
- #find_name(full_name) ⇒ Object
-
#initialize(development = false) ⇒ DependencyList
constructor
Creates a new DependencyList.
-
#inspect ⇒ Object
:nodoc:.
-
#ok? ⇒ Boolean
Are all the dependencies in the list satisfied?.
-
#ok_to_remove?(full_name, check_dev = true) ⇒ Boolean
It is ok to remove a gemspec from the dependency list?.
-
#remove_by_name(full_name) ⇒ Object
Removes the gemspec matching
full_name
from the dependency list. -
#remove_specs_unsatisfied_by(dependencies) ⇒ Object
Remove everything in the DependencyList that matches but doesn’t satisfy items in
dependencies
(a hash of gem names to arrays of dependencies). -
#spec_predecessors ⇒ Object
Return a hash of predecessors.
- #tsort_each_child(node) ⇒ Object
- #tsort_each_node(&block) ⇒ Object
- #why_not_ok?(quick = false) ⇒ Boolean
Constructor Details
#initialize(development = false) ⇒ DependencyList
Creates a new DependencyList. If development
is true, development dependencies will be included.
44 45 46 47 48 |
# File 'lib/rubygems/dependency_list.rb', line 44 def initialize(development = false) @specs = [] @development = development end |
Instance Attribute Details
#development ⇒ Object
Allows enabling/disabling use of development dependencies
29 30 31 |
# File 'lib/rubygems/dependency_list.rb', line 29 def development @development end |
#specs ⇒ Object (readonly)
Returns the value of attribute specs
21 22 23 |
# File 'lib/rubygems/dependency_list.rb', line 21 def specs @specs end |
Class Method Details
.from_specs ⇒ Object
Creates a DependencyList from the current specs.
34 35 36 37 38 |
# File 'lib/rubygems/dependency_list.rb', line 34 def self.from_specs list = new list.add(*Gem::Specification.to_a) list end |
Instance Method Details
#add(*gemspecs) ⇒ Object
Adds gemspecs
to the dependency list.
53 54 55 |
# File 'lib/rubygems/dependency_list.rb', line 53 def add(*gemspecs) @specs.concat gemspecs end |
#clear ⇒ Object
57 58 59 |
# File 'lib/rubygems/dependency_list.rb', line 57 def clear @specs.clear end |
#dependency_order ⇒ Object
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.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/rubygems/dependency_list.rb', line 76 def dependency_order sorted = strongly_connected_components.flatten result = [] seen = {} sorted.each do |spec| if index = seen[spec.name] if result[index].version < spec.version result[index] = spec end else seen[spec.name] = result.length result << spec end end result.reverse end |
#each(&block) ⇒ Object
Iterator over dependency_order
99 100 101 |
# File 'lib/rubygems/dependency_list.rb', line 99 def each(&block) dependency_order.each(&block) end |
#find_name(full_name) ⇒ Object
103 104 105 |
# File 'lib/rubygems/dependency_list.rb', line 103 def find_name(full_name) @specs.find { |spec| spec.full_name == full_name } end |
#inspect ⇒ Object
:nodoc:
107 108 109 |
# File 'lib/rubygems/dependency_list.rb', line 107 def inspect # :nodoc: "%s %p>" % [super[0..-2], map { |s| s.full_name }] end |
#ok? ⇒ Boolean
Are all the dependencies in the list satisfied?
114 115 116 |
# File 'lib/rubygems/dependency_list.rb', line 114 def ok? why_not_ok?(:quick).empty? end |
#ok_to_remove?(full_name, check_dev = true) ⇒ Boolean
It 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.
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/rubygems/dependency_list.rb', line 143 def ok_to_remove?(full_name, check_dev=true) gem_to_remove = find_name full_name # If the state is inconsistent, at least don't crash return true unless gem_to_remove siblings = @specs.find_all do |s| s.name == gem_to_remove.name && s.full_name != gem_to_remove.full_name end deps = [] @specs.each do |spec| check = check_dev ? spec.dependencies : spec.runtime_dependencies check.each do |dep| deps << dep if gem_to_remove.satisfies_requirement?(dep) end end deps.all? do |dep| siblings.any? do |s| s.satisfies_requirement? dep end end end |
#remove_by_name(full_name) ⇒ Object
Removes the gemspec matching full_name
from the dependency list
186 187 188 |
# File 'lib/rubygems/dependency_list.rb', line 186 def remove_by_name(full_name) @specs.delete_if { |spec| spec.full_name == full_name } end |
#remove_specs_unsatisfied_by(dependencies) ⇒ Object
Remove everything in the DependencyList that matches but doesn’t satisfy items in dependencies
(a hash of gem names to arrays of dependencies).
176 177 178 179 180 181 |
# File 'lib/rubygems/dependency_list.rb', line 176 def remove_specs_unsatisfied_by(dependencies) specs.reject! do |spec| dep = dependencies[spec.name] dep and not dep.requirement.satisfied_by? spec.version end end |
#spec_predecessors ⇒ Object
Return a hash of predecessors. result[spec]
is an Array of gemspecs that have a dependency satisfied by the named gemspec.
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/rubygems/dependency_list.rb', line 194 def spec_predecessors result = Hash.new { |h,k| h[k] = [] } specs = @specs.sort.reverse specs.each do |spec| specs.each do |other| next if spec == other other.dependencies.each do |dep| if spec.satisfies_requirement? dep result[spec] << other end end end end result end |
#tsort_each_child(node) ⇒ Object
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/rubygems/dependency_list.rb', line 218 def tsort_each_child(node) specs = @specs.sort.reverse dependencies = node.runtime_dependencies dependencies.push(*node.development_dependencies) if @development dependencies.each do |dep| specs.each do |spec| if spec.satisfies_requirement? dep yield spec break end end end end |
#tsort_each_node(&block) ⇒ Object
214 215 216 |
# File 'lib/rubygems/dependency_list.rb', line 214 def tsort_each_node(&block) @specs.each(&block) end |
#why_not_ok?(quick = false) ⇒ Boolean
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/rubygems/dependency_list.rb', line 118 def why_not_ok?(quick = false) unsatisfied = Hash.new { |h,k| h[k] = [] } each do |spec| spec.runtime_dependencies.each do |dep| inst = Gem::Specification.any? do |installed_spec| dep.name == installed_spec.name and dep.requirement.satisfied_by? installed_spec.version end unless inst or @specs.find { |s| s.satisfies_requirement? dep } unsatisfied[spec.name] << dep return unsatisfied if quick end end end unsatisfied end |