solve 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 868022031f083b30e7c32a6d424896fb2fb08367
4
- data.tar.gz: 5d50e154ab203dbddd6888616295fc683f26672c
3
+ metadata.gz: 96b860730518abd99eb79c2d9b847fc6b4b13d5c
4
+ data.tar.gz: 95635f8ef60cce43ff1b92e7800e749ef1666659
5
5
  SHA512:
6
- metadata.gz: 56abef15a6d5da9a0e31e1ed88cc46ce9acb7aab8526ec7aaf0c615e8f09cfa1fbb0b361349282640813328fecc954f9eb75fea5d73764176964b771c1a467ec
7
- data.tar.gz: 0a079122af8824f23e23c69649092b4f32c7cbb44f72e4fc9d754350c45a48580280e758bb8e94269d6edba99ed026c379399d1edd38fe49afa53b70acfbc84c
6
+ metadata.gz: 5742cdbaecdfae7a0dac68f377331b96ee1200ca469e4317a647ec4fb23710520afd46051468ce9509ba81952c508cbb12dccc50323f35c00aa75d2c6f20df43
7
+ data.tar.gz: f6602ad5b6a9e9e07e052e779727b9a8f24abc267443af2e9902f6536dcb99b430841f1d72e8ea62b2edfa20b789740675326c6a2499ce4e5bdd35a9a117f61a
data/lib/solve.rb CHANGED
@@ -8,8 +8,12 @@ module Solve
8
8
  require_relative 'solve/graph'
9
9
  require_relative 'solve/solver'
10
10
  require_relative 'solve/version'
11
+ require_relative 'solve/tracers'
11
12
 
12
13
  class << self
14
+ # @return [Solve::Formatter]
15
+ attr_reader :tracer
16
+
13
17
  # A quick solve. Given the "world" as we know it (the graph) and a list of
14
18
  # requirements (demands) which must be met. Return me the best solution of
15
19
  # artifacts and verisons that I should use.
@@ -20,7 +24,10 @@ module Solve
20
24
  # @param [Array<Solve::Demand>, Array<String, String>] demands
21
25
  #
22
26
  # @option options [#say] :ui (nil)
23
- # a ui object for output
27
+ # a ui object for output, this will be used to output from a Solve::Tracers::HumanReadable if
28
+ # no other tracer is provided in options[:tracer]
29
+ # @option options [AbstractTracer] :tracer (nil)
30
+ # a Tracer object that is used to format and output tracing information
24
31
  # @option options [Boolean] :sorted (false)
25
32
  # should the output be a sorted list rather than a Hash
26
33
  #
@@ -28,6 +35,7 @@ module Solve
28
35
  #
29
36
  # @return [Hash]
30
37
  def it!(graph, demands, options = {})
38
+ @tracer = options[:tracer] || Solve::Tracers.build(options[:ui])
31
39
  Solver.new(graph, demands, options[:ui]).resolve(options)
32
40
  end
33
41
  end
@@ -1,3 +1,3 @@
1
1
  module Solve
2
- VERSION = "0.7.0"
2
+ VERSION = "0.8.0"
3
3
  end
data/lib/solve/solver.rb CHANGED
@@ -94,24 +94,20 @@ module Solve
94
94
  # @return [Hash, List] Returns a hash like { "Artifact Name" => "Version",... }
95
95
  # unless options[:sorted], then it returns a list like [["Artifact Name", "Version],...]
96
96
  def resolve(options = {})
97
- trace("Attempting to find a solution")
97
+ Solve.tracer.start
98
98
  seed_demand_dependencies
99
99
 
100
100
  while unbound_variable = variable_table.first_unbound
101
101
  possible_values_for_unbound = possible_values_for(unbound_variable)
102
- trace("Searching for a value for #{unbound_variable.artifact}")
103
- trace("Constraints are")
104
- constraint_table.constraints_on_artifact(unbound_variable.artifact).each do |constraint|
105
- trace("\t#{constraint}")
106
- end
107
- trace("Possible values are #{possible_values_for_unbound}")
102
+ constraints = constraint_table.constraints_on_artifact(unbound_variable.artifact)
103
+ Solve.tracer.searching_for(unbound_variable, constraints, possible_values)
108
104
 
109
105
  while possible_value = possible_values_for_unbound.shift
110
106
  possible_artifact = graph.get_artifact(unbound_variable.artifact, possible_value.version)
111
107
  possible_dependencies = possible_artifact.dependencies
112
108
  all_ok = possible_dependencies.all? { |dependency| can_add_new_constraint?(dependency) }
113
109
  if all_ok
114
- trace("Attempting to use #{possible_artifact}")
110
+ Solve.tracer.trying(possible_artifact)
115
111
  add_dependencies(possible_dependencies, possible_artifact)
116
112
  unbound_variable.bind(possible_value)
117
113
  break
@@ -119,15 +115,13 @@ module Solve
119
115
  end
120
116
 
121
117
  unless unbound_variable.bound?
122
- trace("Could not find an acceptable value for #{unbound_variable.artifact}")
123
118
  backtrack(unbound_variable)
124
119
  end
125
120
  end
126
121
 
127
122
  solution = (options[:sorted]) ? build_sorted_solution : build_unsorted_solution
128
123
 
129
- trace("Found Solution")
130
- trace(solution)
124
+ Solve.tracer.solution(solution)
131
125
 
132
126
  solution
133
127
  end
@@ -266,7 +260,7 @@ module Solve
266
260
 
267
261
  def add_dependencies(dependencies, source)
268
262
  dependencies.each do |dependency|
269
- trace("Adding constraint #{dependency.name} #{dependency.constraint} from #{source}")
263
+ Solve.tracer.add_constraint(dependency, source)
270
264
  variable_table.add(dependency.name, source)
271
265
  constraint_table.add(dependency, source)
272
266
  dependency_domain = graph.versions(dependency.name, dependency.constraint)
@@ -289,41 +283,36 @@ module Solve
289
283
  end
290
284
 
291
285
  def reset_possible_values_for(variable)
292
- trace("Resetting possible values for #{variable.artifact}")
286
+ Solve.tracer.reset_domain(variable)
293
287
  possible_values[variable.artifact] = nil
294
- x = possible_values_for(variable)
295
- trace("Possible values are #{x}")
296
- x
288
+ possible_values_for(variable).tap { |values| Solve.tracer.possible_values(values) }
297
289
  end
298
290
 
299
291
  def backtrack(unbound_variable)
292
+ Solve.tracer.backtrack(unbound_variable)
300
293
  previous_variable = variable_table.before(unbound_variable.artifact)
301
294
 
302
295
  if previous_variable.nil?
303
- trace("Cannot backtrack any further")
296
+ Solve.tracer.cannot_backtrack
304
297
  raise Errors::NoSolutionError
305
298
  end
306
299
 
307
- trace("Unbinding #{previous_variable.artifact}")
300
+ Solve.tracer.unbind(previous_variable)
308
301
 
309
302
  source = previous_variable.value
310
303
  removed_variables = variable_table.remove_all_with_only_this_source!(source)
311
304
  removed_variables.each do |removed_variable|
312
305
  possible_values[removed_variable.artifact] = nil
313
- trace("Removed variable #{removed_variable.artifact}")
306
+ Solve.tracer.remove_variable(removed_variable)
314
307
  end
315
308
  removed_constraints = constraint_table.remove_constraints_from_source!(source)
316
309
  removed_constraints.each do |removed_constraint|
317
- trace("Removed constraint #{removed_constraint.name} #{removed_constraint.constraint}")
310
+ Solve.tracer.remove_constraint(removed_constraint)
318
311
  end
319
312
  previous_variable.unbind
320
313
  variable_table.all_after(previous_variable.artifact).each do |variable|
321
314
  new_possibles = reset_possible_values_for(variable)
322
315
  end
323
316
  end
324
-
325
- def trace(message)
326
- ui.say(message) unless ui.nil?
327
- end
328
317
  end
329
318
  end
@@ -0,0 +1,50 @@
1
+ module Solve
2
+ module Tracers
3
+ class << self
4
+ # @param [#say] ui
5
+ #
6
+ # @returns [AbstractTracer]
7
+ def build(ui)
8
+ unless ui.respond_to?(:say)
9
+ Solve::Tracers::Silent.new
10
+ else
11
+ Solve::Tracers::HumanReadable.new(ui)
12
+ end
13
+ end
14
+ end
15
+
16
+ class AbstractTracer
17
+ class << self
18
+ private
19
+
20
+ def must_define(*args)
21
+ args.each do |method|
22
+ define_method(method.to_sym) do |*args|
23
+ raise AbstractFunction, "##{method} must be defined on #{self.class}"
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ TRACER_METHODS = [
30
+ :start,
31
+ :searching_for,
32
+ :add_constraint,
33
+ :possible_values,
34
+ :trying,
35
+ :backtrack,
36
+ :cannot_backtrack,
37
+ :solution,
38
+ :reset_domain,
39
+ :unbind,
40
+ :remove_variable,
41
+ :remove_constraint,
42
+ ]
43
+
44
+ must_define *TRACER_METHODS
45
+ end
46
+ end
47
+ end
48
+
49
+ require_relative 'tracers/human_readable'
50
+ require_relative 'tracers/silent'
@@ -0,0 +1,67 @@
1
+ module Solve
2
+ module Tracers
3
+ class HumanReadable < AbstractTracer
4
+ extend Forwardable
5
+
6
+ attr_reader :ui
7
+
8
+ def_delegator :ui, :say
9
+
10
+ # @param [#say] ui
11
+ def initialize(ui)
12
+ @ui = ui
13
+ end
14
+
15
+ def start
16
+ say("Attempting to find a solution")
17
+ end
18
+
19
+ def searching_for(unbound_variable, constraints, possible_values)
20
+ say("Searching for a value for #{unbound_variable.artifact}")
21
+ say("Constraints are #{constraints.join("\n\t")}")
22
+ possible_values(possible_values)
23
+ end
24
+
25
+ def possible_values(possible_values)
26
+ say("Possible values are #{possible_values.map(&:to_s).join("\n\t")}")
27
+ end
28
+
29
+ def trying(artifact)
30
+ say("Attempting to use #{artifact.to_s}")
31
+ end
32
+
33
+ def backtrack(unbound_variable)
34
+ say("Could not find an acceptable value for #{unbound_variable.artifact.to_s}")
35
+ end
36
+
37
+ def cannot_backtrack
38
+ say("Cannot backtrack any further")
39
+ end
40
+
41
+ def solution(solution)
42
+ say("Found Solution")
43
+ say(solution)
44
+ end
45
+
46
+ def add_constraint(dependency, source)
47
+ say("Adding constraint #{dependency.name} #{dependency.constraint} from #{source.to_s}")
48
+ end
49
+
50
+ def reset_domain(variable)
51
+ say("Resetting possible values for #{variable.artifact.to_s}")
52
+ end
53
+
54
+ def unbind(variable)
55
+ say("Unbinding #{variable.artifact.to_s}")
56
+ end
57
+
58
+ def remove_variable(variable)
59
+ say("Removed variable #{variable.artifact.to_s}")
60
+ end
61
+
62
+ def remove_constraint(constraint)
63
+ say("Removed constraint #{constraint.name} #{constraint.constraint}")
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,17 @@
1
+ module Solve
2
+ module Tracers
3
+ class Silent < AbstractTracer
4
+ class << self
5
+ def empty_method(*args)
6
+ args.each do |method|
7
+ define_method(method.to_sym) do |*args|
8
+ end
9
+ end
10
+ end
11
+ end
12
+
13
+ empty_method *AbstractTracer::TRACER_METHODS
14
+ end
15
+ end
16
+ end
17
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solve
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamie Winsor
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-07-29 00:00:00.000000000 Z
13
+ date: 2013-07-31 00:00:00.000000000 Z
14
14
  dependencies: []
15
15
  description: A Ruby version constraint solver
16
16
  email:
@@ -43,6 +43,9 @@ files:
43
43
  - lib/solve/solver/serializer.rb
44
44
  - lib/solve/solver/variable_row.rb
45
45
  - lib/solve/solver/variable_table.rb
46
+ - lib/solve/tracers.rb
47
+ - lib/solve/tracers/human_readable.rb
48
+ - lib/solve/tracers/silent.rb
46
49
  - lib/solve/version.rb
47
50
  - solve.gemspec
48
51
  - spec/acceptance/solutions_spec.rb