solve 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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