class PuppetfileResolver::ResolutionProvider

Public Class Methods

new(puppetfile_document, puppet_version, resolver_ui, options = {}) click to toggle source

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

allow_missing?(dependency) click to toggle source

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
dependencies_for(specification) click to toggle source

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
find_puppet_specifications(dependency) click to toggle source
# 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
name_for(dependency) click to toggle source

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
name_for_explicit_dependency_source() click to toggle source
# File lib/puppetfile-resolver/resolution_provider.rb, line 104
def name_for_explicit_dependency_source
  'Puppetfile'
end
name_for_locking_dependency_source() click to toggle source
# File lib/puppetfile-resolver/resolution_provider.rb, line 108
def name_for_locking_dependency_source
  'Puppetfile'
end
requirement_satisfied_by?(requirement, _activated, spec) click to toggle source

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(dependency) click to toggle source

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
sort_dependencies(dependencies, activated, conflicts) click to toggle source
# 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

find_all_module_specifications(dependency) click to toggle source
# 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