Class: 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.
43 44 45 46 47 |
# File 'lib/rubygems/dependency_list.rb', line 43 def initialize(development = false) @specs = [] @development = development end |
Instance Attribute Details
#development ⇒ Object
Allows enabling/disabling use of development dependencies
28 29 30 |
# File 'lib/rubygems/dependency_list.rb', line 28 def development @development end |
#specs ⇒ Object (readonly)
Returns the value of attribute specs.
20 21 22 |
# File 'lib/rubygems/dependency_list.rb', line 20 def specs @specs end |
Class Method Details
.from_specs ⇒ Object
Creates a DependencyList from the current specs.
33 34 35 36 37 |
# File 'lib/rubygems/dependency_list.rb', line 33 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.
52 53 54 |
# File 'lib/rubygems/dependency_list.rb', line 52 def add(*gemspecs) @specs.concat gemspecs end |
#clear ⇒ Object
56 57 58 |
# File 'lib/rubygems/dependency_list.rb', line 56 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.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/rubygems/dependency_list.rb', line 75 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
98 99 100 |
# File 'lib/rubygems/dependency_list.rb', line 98 def each(&block) dependency_order.each(&block) end |
#find_name(full_name) ⇒ Object
102 103 104 |
# File 'lib/rubygems/dependency_list.rb', line 102 def find_name(full_name) @specs.find {|spec| spec.full_name == full_name } end |
#inspect ⇒ Object
:nodoc:
106 107 108 |
# File 'lib/rubygems/dependency_list.rb', line 106 def inspect # :nodoc: "%s %p>" % [super[0..-2], map {|s| s.full_name }] end |
#ok? ⇒ Boolean
Are all the dependencies in the list satisfied?
113 114 115 |
# File 'lib/rubygems/dependency_list.rb', line 113 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.
142 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 |
# File 'lib/rubygems/dependency_list.rb', line 142 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
185 186 187 |
# File 'lib/rubygems/dependency_list.rb', line 185 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).
175 176 177 178 179 180 |
# File 'lib/rubygems/dependency_list.rb', line 175 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.
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/rubygems/dependency_list.rb', line 193 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
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/rubygems/dependency_list.rb', line 217 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
213 214 215 |
# File 'lib/rubygems/dependency_list.rb', line 213 def tsort_each_node(&block) @specs.each(&block) end |
#why_not_ok?(quick = false) ⇒ Boolean
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/rubygems/dependency_list.rb', line 117 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 |