@@ -6,10 +6,13 @@ require "./spec"
6
6
module Shards
7
7
class Solver
8
8
setter locks : Array (Dependency )?
9
+ @solution : Array (Package )?
9
10
10
11
def initialize (@spec : Spec )
11
12
@graph = Graph .new
12
13
@sat = SAT .new
14
+ @solution = nil
15
+ @solution_distance = Int32 ::MAX
13
16
end
14
17
15
18
def prepare (development = true ) : Nil
@@ -20,26 +23,46 @@ module Shards
20
23
def solve : Array (Package )?
21
24
distances = calculate_distances
22
25
23
- solution = nil
24
- solution_distance = Int32 ::MAX
25
-
26
26
@sat .solve do |proposal |
27
27
# calculate the proposal quality (distance from ideal solution):
28
28
distance = proposal.reduce(0 ) { |a , e | a + distances[e] }
29
29
30
- if distance < solution_distance
30
+ if distance < @ solution_distance
31
31
# select better solution (less distance from ideal):
32
- solution = proposal.dup
33
- solution_distance = distance
32
+ consider(proposal, distance)
34
33
35
- elsif distance == solution_distance && proposal.size < solution.not_nil!.size
34
+ elsif distance == @ solution_distance && proposal.size < @ solution .not_nil!.size
36
35
# select solution with fewer dependencies (same distance from ideal):
37
- solution = proposal.dup
38
- solution_distance = distance
36
+ consider(proposal, distance)
37
+ end
38
+ end
39
+
40
+ @solution
41
+ end
42
+
43
+ private def consider (proposal , distance )
44
+ packages = to_packages(proposal)
45
+
46
+ # pre-releases are opt-in, so we must check that the solution didn't
47
+ # select one unless at least one requirement in the selected graph asked
48
+ # for it:
49
+ packages.each do |package |
50
+ next unless Versions .prerelease?(package.version)
51
+
52
+ if dependency = @spec .dependencies.find { |d | d.name == package.name }
53
+ break if Versions .prerelease?(dependency.version)
54
+ end
55
+
56
+ return unless packages.any? do |pkg |
57
+ if dependency = pkg.spec.dependencies.find { |d | d.name == package.name }
58
+ Versions .prerelease?(dependency.version)
59
+ end
39
60
end
40
61
end
41
62
42
- to_packages(solution) if solution
63
+ # solution is acceptable:
64
+ @solution = packages
65
+ @solution_distance = distance
43
66
end
44
67
45
68
private def to_packages (solution )
0 commit comments