Class: Gem::DependencyList

Inherits:
Object
  • Object
show all
Extended by:
Deprecate
Includes:
Enumerable, TSort
Defined in:
lib/rubygems/dependency_list.rb,
lib/rubygems/dependency_list.rb

Overview

Gem::DependencyList is used for installing and uninstalling gems in the correct order to avoid conflicts.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Deprecate

deprecate, skip, skip=, skip_during

Constructor Details

#initialize(development = false) ⇒ DependencyList

Creates a new DependencyList. If development is true, development dependencies will be included.



47
48
49
50
51
# File 'lib/rubygems/dependency_list.rb', line 47

def initialize development = false
  @specs = []

  @development = development
end

Instance Attribute Details

#developmentObject

Allows enabling/disabling use of development dependencies



23
24
25
# File 'lib/rubygems/dependency_list.rb', line 23

def development
  @development
end

#specsObject (readonly)

Returns the value of attribute specs



15
16
17
# File 'lib/rubygems/dependency_list.rb', line 15

def specs
  @specs
end

Class Method Details

.from_source_index(ignored = nil) ⇒ Object

Creates a DependencyList from a Gem::SourceIndex source_index



37
38
39
40
41
# File 'lib/rubygems/dependency_list.rb', line 37

def self.from_source_index(ignored=nil)
  warn "NOTE: DependencyList.from_source_index ignores it's arg" if ignored

  from_specs
end

.from_specsObject

Creates a DependencyList from the current specs.



28
29
30
31
32
# File 'lib/rubygems/dependency_list.rb', line 28

def self.from_specs
  list = new
  list.add(*Gem::Specification.map)
  list
end

Instance Method Details

#add(*gemspecs) ⇒ Object

Adds gemspecs to the dependency list.



56
57
58
# File 'lib/rubygems/dependency_list.rb', line 56

def add(*gemspecs)
  @specs.push(*gemspecs)
end

#clearObject



60
61
62
# File 'lib/rubygems/dependency_list.rb', line 60

def clear
  @specs.clear
end

#dependency_orderObject

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.



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/rubygems/dependency_list.rb', line 79

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



102
103
104
# File 'lib/rubygems/dependency_list.rb', line 102

def each(&block)
  dependency_order.each(&block)
end

#find_name(full_name) ⇒ Object



106
107
108
# File 'lib/rubygems/dependency_list.rb', line 106

def find_name(full_name)
  @specs.find { |spec| spec.full_name == full_name }
end

#inspectObject

:nodoc:



110
111
112
# File 'lib/rubygems/dependency_list.rb', line 110

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?

Returns:

  • (Boolean)


117
118
119
# File 'lib/rubygems/dependency_list.rb', line 117

def ok?
  why_not_ok?(:quick).empty?
end

#ok_to_remove?(full_name) ⇒ 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.

Returns:

  • (Boolean)


146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/rubygems/dependency_list.rb', line 146

def ok_to_remove?(full_name)
  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|
    spec.dependencies.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



184
185
186
# File 'lib/rubygems/dependency_list.rb', line 184

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).



174
175
176
177
178
179
# File 'lib/rubygems/dependency_list.rb', line 174

def remove_specs_unsatisfied_by dependencies
  specs.reject! { |spec|
    dep = dependencies[spec.name]
    dep and not dep.requirement.satisfied_by? spec.version
  }
end

#spec_predecessorsObject

Return a hash of predecessors. result[spec] is an Array of gemspecs that have a dependency satisfied by the named gemspec.



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/rubygems/dependency_list.rb', line 192

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, &block) ⇒ Object



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/rubygems/dependency_list.rb', line 216

def tsort_each_child(node, &block)
  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



212
213
214
# File 'lib/rubygems/dependency_list.rb', line 212

def tsort_each_node(&block)
  @specs.each(&block)
end

#why_not_ok?(quick = false) ⇒ Boolean

Returns:

  • (Boolean)


121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/rubygems/dependency_list.rb', line 121

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