1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
|
require 'semantic_puppet/dependency'
require 'set'
module SemanticPuppet
module Dependency
module GraphNode
include Comparable
def name
end
# Determines whether the modules dependencies are satisfied by the known
# releases.
#
# @return [Boolean] true if all dependencies are satisfied
def satisfied?
dependencies.none? { |_, v| v.empty? }
end
def children
@_children ||= {}
end
def populate_children(nodes)
if children.empty?
nodes = nodes.select { |node| satisfies_dependency?(node) }
nodes.each do |node|
children[node.name] = node
node.populate_children(nodes)
end
self.freeze
end
end
# @api internal
# @return [{ String => Array<GraphNode> }] the satisfactory
# dependency nodes
def dependencies
@_dependencies ||= Hash.new { |h, k| h[k] = Array.new }
end
# Adds the given dependency name to the list of dependencies.
#
# @param name [String] the dependency name
# @return [void]
def add_dependency(name)
dependencies[name]
end
# @return [Array<String>] the list of dependency names
def dependency_names
dependencies.keys
end
def constraints
@_constraints ||= Hash.new { |h, k| h[k] = [] }
end
def constraints_for(name)
return [] unless constraints.has_key?(name)
constraints[name].map do |constraint|
{
:source => constraint[0],
:description => constraint[1],
:test => constraint[2],
}
end
end
# Constrains the named module to suitable releases, as determined by the
# given block.
#
# @example Version-locking currently installed modules
# installed_modules.each do |m|
# @graph.add_constraint('installed', m.name, m.version) do |node|
# m.version == node.version
# end
# end
#
# @param source [String, Symbol] a name describing the source of the
# constraint
# @param mod [String] the name of the module
# @param desc [String] a description of the enforced constraint
# @yieldparam node [GraphNode] the node to test the constraint against
# @yieldreturn [Boolean] whether the node passed the constraint
# @return [void]
def add_constraint(source, mod, desc, &block)
constraints["#{mod}"] << [ source, desc, block ]
end
def satisfies_dependency?(node)
dependencies.key?(node.name) && satisfies_constraints?(node)
end
# @param release [ModuleRelease] the release to test
def satisfies_constraints?(release)
constraints_for(release.name).all? { |x| x[:test].call(release) }
end
def << (nodes)
Array(nodes).group_by(&:name).each_pair do |name, nodes|
changed = false
next unless dependencies.key?(name)
nodes.each do |node|
if satisfies_dependency?(node)
dependencies[name] << node
changed = true
end
end
dependencies[name].sort! if changed
end
return self
end
def <=>(other)
name <=> other.name
end
end
end
end
|