123456789_123456789_123456789_123456789_123456789_

Class: Gem::DependencyList

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
self, TSort, Enumerable
Inherits: Object
Defined in: lib/rubygems/dependency_list.rb

Overview

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

Class Method Summary

Instance Attribute Summary

Instance Method Summary

TSort - Included

#each_strongly_connected_component

The iterator version of the #strongly_connected_components method.

#each_strongly_connected_component_from

Iterates over strongly connected component in the subgraph reachable from node.

#strongly_connected_components

Returns strongly connected components as an array of arrays of nodes.

#tsort

Returns a topologically sorted array of nodes.

#tsort_each

The iterator version of the #tsort method.

#tsort_each_child

Should be implemented by a extended class.

#tsort_each_node

Should be implemented by a extended class.

Constructor Details

.new(development = false) ⇒ DependencyList

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

[ GitHub ]

  
# File 'lib/rubygems/dependency_list.rb', line 44

def initialize(development = false)
  @specs = []

  @development = development
end

Class Method Details

.from_specs

Creates a DependencyList from the current specs.

[ GitHub ]

  
# File 'lib/rubygems/dependency_list.rb', line 34

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

Instance Attribute Details

#development (rw)

Allows enabling/disabling use of development dependencies

[ GitHub ]

  
# File 'lib/rubygems/dependency_list.rb', line 29

attr_accessor :development

#ok?Boolean (readonly)

Are all the dependencies in the list satisfied?

[ GitHub ]

  
# File 'lib/rubygems/dependency_list.rb', line 114

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

#specs (readonly)

[ GitHub ]

  
# File 'lib/rubygems/dependency_list.rb', line 21

attr_reader :specs

Instance Method Details

#active_count(specs, ignored) (private)

Count the number of gemspecs in the list #specs that are not in ignored.

[ GitHub ]

  
# File 'lib/rubygems/dependency_list.rb', line 240

def active_count(specs, ignored)
  specs.count {|spec| ignored[spec.full_name].nil? }
end

#add(*gemspecs)

Adds gemspecs to the dependency list.

[ GitHub ]

  
# File 'lib/rubygems/dependency_list.rb', line 53

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

#clear

[ GitHub ]

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

def clear
  @specs.clear
end

#dependency_order

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.

[ GitHub ]

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

Iterator over dependency_order

[ GitHub ]

  
# File 'lib/rubygems/dependency_list.rb', line 99

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

#find_name(full_name)

[ GitHub ]

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

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

#inspect

This method is for internal use only.
[ GitHub ]

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

def inspect # :nodoc:
  "%s %p>" % [super[0..-2], map {|s| s.full_name }]
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.

[ GitHub ]

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

Removes the gemspec matching full_name from the dependency list

[ GitHub ]

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

Remove everything in the DependencyList that matches but doesn’t satisfy items in dependencies (a hash of gem names to arrays of dependencies).

[ GitHub ]

  
# File 'lib/rubygems/dependency_list.rb', line 176

def remove_specs_unsatisfied_by(dependencies)
  specs.reject! do |spec|
    dep = dependencies[spec.name]
    dep && !dep.requirement.satisfied_by?(spec.version)
  end
end

#spec_predecessors

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

[ GitHub ]

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

[ GitHub ]

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

[ GitHub ]

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

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

#why_not_ok?(quick = false) ⇒ Boolean

[ GitHub ]

  
# 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 &&
          dep.requirement.satisfied_by?(installed_spec.version)
      end

      unless inst || @specs.find {|s| s.satisfies_requirement? dep }
        unsatisfied[spec.name] << dep
        return unsatisfied if quick
      end
    end
  end

  unsatisfied
end