class PuppetfileResolver::ResolutionProvider
Public Class Methods
options
module_paths : Array of paths (Deprecated) strict_mode : [Boolean] Whether missing dependencies throw an error (default: false) spec_searcher_configuration : PuppetfileResolver::SpecSearchers::Configuration
# File lib/puppetfile-resolver/resolution_provider.rb, line 18 def initialize(puppetfile_document, puppet_version, resolver_ui, options = {}) require 'semantic_puppet' @puppetfile_document = puppetfile_document raise 'The UI object must be of type Molinillo::UI' if resolver_ui.nil? || !resolver_ui.is_a?(Molinillo::UI) @resolver_ui = resolver_ui @spec_searcher_configuration = options[:spec_searcher_configuration] || PuppetfileResolver::SpecSearchers::Configuration.new @allow_missing_modules = options[:allow_missing_modules].nil? ? true : options[:allow_missing_modules] == true # There can be only one puppet specification in existance so we pre-load here. @puppet_specification = Models::PuppetSpecification.new(puppet_version) @module_info = {} @cache = options[:cache].nil? ? Cache::Base.new : options[:cache] # Check for deprecated options unless options[:module_paths].nil? # rubocop:disable Style/GuardClause Warning.warn 'The use of the module_paths option has been deprecated' @spec_searcher_configuration.local.puppet_module_paths = options[:module_paths] end end
Public Instance Methods
Returns whether this dependency, which has no possible matching specifications, can safely be ignored.
@param [Object] dependency @return [Boolean] whether this dependency can safely be skipped.
# File lib/puppetfile-resolver/resolution_provider.rb, line 127 def allow_missing?(dependency) # Puppet dependencies must _always_ be resolvable return false if dependency.is_a?(Models::PuppetDependency) # Explicit Puppetfile dependencies must _always_ be resolvable return false if dependency.is_a?(Models::PuppetfileDependency) @allow_missing_modules end
Returns the dependencies of `specification`. @note This method should be 'pure', i.e. the return value should depend
only on the `specification` parameter.
@param [Object] specification @return [Array<Object>] the dependencies that are required by the given
`specification`.
# File lib/puppetfile-resolver/resolution_provider.rb, line 77 def dependencies_for(specification) specification.dependencies(@cache, @resolver_ui) end
# File lib/puppetfile-resolver/resolution_provider.rb, line 65 def find_puppet_specifications(dependency) # Puppet specifications are a bit special as there can be only one (Highlander style) dependency.satisified_by?(@puppet_specification) ? [@puppet_specification] : [] end
Returns the name for the given `dependency`. @note This method should be 'pure', i.e. the return value should depend
only on the `dependency` parameter.
@param [Object] dependency @return [String] the name for the given `dependency`.
# File lib/puppetfile-resolver/resolution_provider.rb, line 87 def name_for(dependency) dependency.name end
# File lib/puppetfile-resolver/resolution_provider.rb, line 104 def name_for_explicit_dependency_source 'Puppetfile' end
# File lib/puppetfile-resolver/resolution_provider.rb, line 108 def name_for_locking_dependency_source 'Puppetfile' end
Determines whether the given `requirement` is satisfied by the given `spec`, in the context of the current `activated` dependency graph.
@param [Object] requirement @param [DependencyGraph] activated the current dependency graph in the
resolution process.
@param [Object] spec @return [Boolean] whether `requirement` is satisfied by `spec` in the
context of the current `activated` dependency graph.
# File lib/puppetfile-resolver/resolution_provider.rb, line 100 def requirement_satisfied_by?(requirement, _activated, spec) requirement.satisified_by?(spec) end
Search for the specifications that match the given dependency. The specifications in the returned array will be considered in reverse order, so the latest version ought to be last. @note This method should be 'pure', i.e. the return value should depend
only on the `dependency` parameter.
@param [Object] dependency @return [Array<Object>] the specifications that satisfy the given
`dependency`.
# File lib/puppetfile-resolver/resolution_provider.rb, line 47 def search_for(dependency) case dependency when Models::PuppetDependency result = find_puppet_specifications(dependency) when Models::ModuleDependency result = find_all_module_specifications(dependency).select do |spec| dependency.satisified_by?(spec) end else # No idea how we got here?!?! raise ArgumentError, "Unknown Dependency type #{dependency.class}" end return result if result.empty? || result.count == 1 # Reverse sort by version result.sort! { |a, b| a.version > b.version ? 1 : -1 } end
# File lib/puppetfile-resolver/resolution_provider.rb, line 112 def sort_dependencies(dependencies, activated, conflicts) # rubocop:disable Lint/UnusedMethodArgument You're drunk rubocop dependencies.sort_by do |dependency| name = name_for(dependency) [ activated.vertex_named(name).payload ? 0 : 1, conflicts[name] ? 0 : 1 ] end end
Private Instance Methods
# File lib/puppetfile-resolver/resolution_provider.rb, line 137 def find_all_module_specifications(dependency) return @module_info[dependency.name] unless @module_info[dependency.name].nil? @module_info[dependency.name] = [] # Find the module as specified in the Puppetfile? mod = @puppetfile_document.modules.find { |item| item.name == dependency.name } unless mod.nil? case mod.module_type when Puppetfile::FORGE_MODULE @module_info[dependency.name] = safe_spec_search(dependency) { SpecSearchers::Forge.find_all(dependency, @cache, @resolver_ui, @spec_searcher_configuration.forge) } when Puppetfile::GIT_MODULE @module_info[dependency.name] = safe_spec_search(dependency) { SpecSearchers::Git.find_all(mod, dependency, @cache, @resolver_ui, @spec_searcher_configuration.git) } else # rubocop:disable Style/EmptyElse # Errr.... Nothing end end return @module_info[dependency.name] unless @module_info[dependency.name].empty? # It's not in the Puppetfile, so perhaps it's in our modulepath? @module_info[dependency.name] = safe_spec_search(dependency) { SpecSearchers::Local.find_all(mod, dependency, @cache, @resolver_ui, @spec_searcher_configuration.local) } return @module_info[dependency.name] unless @module_info[dependency.name].empty? # It's not in the Puppetfile and not on disk, so perhaps it's on the Forge? # The forge needs an owner and name to be able to resolve if dependency.name && dependency.owner # rubocop:disable Style/IfUnlessModifier @module_info[dependency.name] = safe_spec_search(dependency) { SpecSearchers::Forge.find_all(dependency, @cache, @resolver_ui, @spec_searcher_configuration.forge) } end # If we can't find any specifications for the module and we're allowing missing modules # then create a MissingModuleSpecification for the purposes of the dependency graph if @allow_missing_modules && @module_info[dependency.name].empty? # rubocop:disable Style/IfUnlessModifier @module_info[dependency.name] << Models::MissingModuleSpecification.new(name: dependency.name) end @module_info[dependency.name] end
# File lib/puppetfile-resolver/resolution_provider.rb, line 174 def safe_spec_search(dependency) results = yield # The PuppetfileDependency has the resolver flags, so we need to inject them into the specifications return results unless dependency.is_a?(PuppetfileResolver::Models::PuppetfileDependency) || results.empty? results.each { |spec| spec.resolver_flags = dependency.puppetfile_module.resolver_flags } results rescue StandardError => e if @allow_missing_modules @resolver_ui.debug { "Error while querying a specification searcher #{e.inspect}" } return [] end raise end