Class: Solve::RubySolver

Inherits:
Object
  • Object
show all
Defined in:
lib/solve/ruby_solver.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(graph, demands, options = {}) ⇒ RubySolver

Returns a new instance of RubySolver.

Examples:

Basic use:

graph = Solve::Graph.new
graph.artifacts("mysql", "1.2.0")
demands = [["mysql"]]
RubySolver.new(graph, demands)

Parameters:

  • graph (Solve::Graph)
  • demands (Array<String>, Array<Array<String, String>>)


42
43
44
45
46
47
48
49
50
51
# File 'lib/solve/ruby_solver.rb', line 42

def initialize(graph, demands, options = {})
  @graph         = graph
  @demands_array = demands
  @timeout_ms    = self.class.timeout

  @dependency_source = options[:dependency_source] || 'user-specified dependency'

  @molinillo_graph = Molinillo::DependencyGraph.new
  @resolver = Molinillo::Resolver.new(self, self)
end

Instance Attribute Details

#demands_arrayArray<String>, Array<Array<String, String>> (readonly)

Returns demands.

Examples:

Demands are Arrays of Arrays with an artifact name and optional constraint:

[['nginx', '= 1.0.0'], ['mysql']]

Returns:

  • (Array<String>, Array<Array<String, String>>)

    demands



33
34
35
# File 'lib/solve/ruby_solver.rb', line 33

def demands_array
  @demands_array
end

#graphSolve::Graph (readonly)

Graph object with references to all known artifacts and dependency constraints.

Returns:



28
29
30
# File 'lib/solve/ruby_solver.rb', line 28

def graph
  @graph
end

Class Method Details

.activateObject

For optinal solver engines, this attempts to load depenencies. The RubySolver is a non-optional component, so this is a no-op



19
20
21
# File 'lib/solve/ruby_solver.rb', line 19

def activate
  true
end

.timeoutInteger

The timeout (in seconds) to use when resolving graphs. Default is 10. This can be configured by setting the SOLVE_TIMEOUT environment variable.

Returns:

  • (Integer)


12
13
14
15
# File 'lib/solve/ruby_solver.rb', line 12

def timeout
  seconds = 30 unless seconds = ENV["SOLVE_TIMEOUT"]
  seconds.to_i * 1_000
end

Instance Method Details

#after_resolutionObject

Callback required by Molinillo, called when the solve is complete.

Returns:

  • nil



111
112
113
# File 'lib/solve/ruby_solver.rb', line 111

def after_resolution
  nil
end

#before_resolutionObject

Callback required by Molinillo, called when the solve starts

Returns:

  • nil



105
106
107
# File 'lib/solve/ruby_solver.rb', line 105

def before_resolution
  nil
end

#debug(current_resolver_depth) ⇒ Object

Callback required by Molinillo, gives debug information about the solution

Returns:

  • nil



117
118
119
120
121
# File 'lib/solve/ruby_solver.rb', line 117

def debug(current_resolver_depth)
  # debug info will be returned if you call yield here, but it seems to be
  # broken in current Molinillo
  nil
end

#demandsArray<Solve::Demand>

The problem demands given as Demand model objects

Returns:



55
56
57
58
59
# File 'lib/solve/ruby_solver.rb', line 55

def demands
  demands_array.map do |name, constraint|
    Demand.new(self, name, constraint)
  end
end

#dependencies_for(specification) ⇒ Array<Solve::Dependency>

Callback required by Molinillo

Returns:



158
159
160
# File 'lib/solve/ruby_solver.rb', line 158

def dependencies_for(specification)
  specification.dependencies
end

#name_for(dependency) ⇒ String

Callback required by Molinillo

Returns:

  • (String)

    the dependency’s name



125
126
127
# File 'lib/solve/ruby_solver.rb', line 125

def name_for(dependency)
  dependency.name
end

#name_for_explicit_dependency_sourceString

Returns the name of the source of explicit dependencies, i.e. those passed to Resolver#resolve directly.

Returns:

  • (String)

    the name of the source of explicit dependencies, i.e. those passed to Resolver#resolve directly.



164
165
166
# File 'lib/solve/ruby_solver.rb', line 164

def name_for_explicit_dependency_source
  @dependency_source
end

#name_for_locking_dependency_sourceString

Returns the name of the source of ‘locked’ dependencies, i.e. those passed to Resolver#resolve directly as the ‘base`.

Returns:

  • (String)

    the name of the source of ‘locked’ dependencies, i.e. those passed to Resolver#resolve directly as the ‘base`



170
171
172
# File 'lib/solve/ruby_solver.rb', line 170

def name_for_locking_dependency_source
  'Lockfile'
end

#progress_rateInteger

Callback required by Molinillo, called when the solve starts

Returns:

  • (Integer)


99
100
101
# File 'lib/solve/ruby_solver.rb', line 99

def progress_rate
  1
end

#requirement_satisfied_by?(requirement, activated, spec) ⇒ Boolean

Callback required by Molinillo

Returns:

  • (Boolean)


152
153
154
# File 'lib/solve/ruby_solver.rb', line 152

def requirement_satisfied_by?(requirement, activated, spec)
  requirement.constraint.satisfies?(spec.version)
end

#resolve(options = {}) ⇒ Hash, List

Returns a hash like { “Artifact Name” => “Version”,… } unless the :sorted option is true, then it returns a list like [[“Artifact Name”, “Version],…]

Parameters:

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :sorted (Boolean)

    return the solution as a sorted list instead of a Hash

Returns:

  • (Hash, List)

    Returns a hash like { “Artifact Name” => “Version”,… } unless the :sorted option is true, then it returns a list like [[“Artifact Name”, “Version],…]

Raises:



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/solve/ruby_solver.rb', line 71

def resolve(options = {})
  solved_graph = resolve_with_error_wrapping

  solution =  solved_graph.map(&:payload)

  unsorted_solution = solution.inject({}) do |stringified_soln, artifact|
    stringified_soln[artifact.name] = artifact.version.to_s
    stringified_soln
  end

  if options[:sorted]
    build_sorted_solution(unsorted_solution)
  else
    unsorted_solution
  end
end

#search_for(dependency) ⇒ Array<Solve::Artifact>

Callback required by Molinillo

Returns:



144
145
146
147
148
# File 'lib/solve/ruby_solver.rb', line 144

def search_for(dependency)
  # This array gets mutated by Molinillo; it's okay because sort returns a
  # new array.
  graph.versions(dependency.name, dependency.constraint).sort
end

#sort_dependencies(dependencies, activated, conflicts) ⇒ Array<Solve::Dependency>

Callback required by Molinillo

Returns:



131
132
133
134
135
136
137
138
139
140
# File 'lib/solve/ruby_solver.rb', line 131

def sort_dependencies(dependencies, activated, conflicts)
  dependencies.sort_by do |dependency|
    name = name_for(dependency)
    [
      activated.vertex_named(name).payload ? 0 : 1,
      conflicts[name] ? 0 : 1,
      activated.vertex_named(name).payload ? 0 : graph.versions(dependency.name).count,
    ]
  end
end