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
Is 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.
42 43 44 45 46 |
# File 'lib/rubygems/dependency_list.rb', line 42 def initialize development = false @specs = [] @development = development end |
Instance Attribute Details
#development ⇒ Object
Allows enabling/disabling use of development dependencies
27 28 29 |
# File 'lib/rubygems/dependency_list.rb', line 27 def development @development end |
#specs ⇒ Object (readonly)
Returns the value of attribute specs.
19 20 21 |
# File 'lib/rubygems/dependency_list.rb', line 19 def specs @specs end |
Class Method Details
.from_specs ⇒ Object
Creates a DependencyList from the current specs.
32 33 34 35 36 |
# File 'lib/rubygems/dependency_list.rb', line 32 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.
51 52 53 |
# File 'lib/rubygems/dependency_list.rb', line 51 def add(*gemspecs) @specs.concat gemspecs end |
#clear ⇒ Object
55 56 57 |
# File 'lib/rubygems/dependency_list.rb', line 55 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.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/rubygems/dependency_list.rb', line 74 def dependency_order sorted = strongly_connected_components.flatten result = [] seen = {} sorted.each do |spec| if index = seen[spec.name] then if result[index].version < spec.version then result[index] = spec end else seen[spec.name] = result.length result << spec end end result.reverse end |
#each(&block) ⇒ Object
Iterator over dependency_order
97 98 99 |
# File 'lib/rubygems/dependency_list.rb', line 97 def each(&block) dependency_order.each(&block) end |
#find_name(full_name) ⇒ Object
101 102 103 |
# File 'lib/rubygems/dependency_list.rb', line 101 def find_name(full_name) @specs.find { |spec| spec.full_name == full_name } end |
#inspect ⇒ Object
:nodoc:
105 106 107 |
# File 'lib/rubygems/dependency_list.rb', line 105 def inspect # :nodoc: "#<%s:0x%x %p>" % [self.class, object_id, map { |s| s.full_name }] end |
#ok? ⇒ Boolean
Are all the dependencies in the list satisfied?
112 113 114 |
# File 'lib/rubygems/dependency_list.rb', line 112 def ok? why_not_ok?(:quick).empty? end |
#ok_to_remove?(full_name, check_dev = true) ⇒ Boolean
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.
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/rubygems/dependency_list.rb', line 141 def ok_to_remove?(full_name, check_dev=true) gem_to_remove = find_name full_name siblings = @specs.find_all { |s| s.name == gem_to_remove.name && s.full_name != gem_to_remove.full_name } 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? { |dep| siblings.any? { |s| s.satisfies_requirement? dep } } end |
#remove_by_name(full_name) ⇒ Object
Removes the gemspec matching full_name
from the dependency list
181 182 183 |
# File 'lib/rubygems/dependency_list.rb', line 181 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).
171 172 173 174 175 176 |
# File 'lib/rubygems/dependency_list.rb', line 171 def remove_specs_unsatisfied_by dependencies specs.reject! { |spec| dep = dependencies[spec.name] dep and not dep.requirement.satisfied_by? spec.version } 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.
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/rubygems/dependency_list.rb', line 189 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 then result[spec] << other end end end end result end |
#tsort_each_child(node) ⇒ Object
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/rubygems/dependency_list.rb', line 213 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 then begin yield spec rescue TSort::Cyclic # do nothing end break end end end end |
#tsort_each_node(&block) ⇒ Object
209 210 211 |
# File 'lib/rubygems/dependency_list.rb', line 209 def tsort_each_node(&block) @specs.each(&block) end |
#why_not_ok?(quick = false) ⇒ Boolean
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/rubygems/dependency_list.rb', line 116 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? { |installed_spec| dep.name == installed_spec.name and dep.requirement.satisfied_by? installed_spec.version } unless inst or @specs.find { |s| s.satisfies_requirement? dep } then unsatisfied[spec.name] << dep return unsatisfied if quick end end end unsatisfied end |