Skip to content

Commit 04d93e4

Browse files
committed
Lock command: read lockfile and updates
- The lock command now reads the lockfile and passes it to the solver. - The solver calculates the distance based on the locked version if present and locked, otherwise aims for the latest release. - The solver always aims for the latest version when the --update command line flag is set. These changes enable the following scenarios: - running the lock command twice without changing dependency requirements shall lock the same versions; - adding a new dependency, or changing a dependency requirement, shall update the minimum number of other dependencies to satisfy the new dependency (or changed requirements); - removing a dependency shall remove extraneous dependencies and update none.
1 parent 4775b9f commit 04d93e4

File tree

3 files changed

+29
-18
lines changed

3 files changed

+29
-18
lines changed

src/cli.cr

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ module Shards
4848
when "list"
4949
Commands::List.run(path, tree: args.includes?("--tree"))
5050
when "lock"
51-
Commands::Lock.run(path, print: args.includes?("--print"))
51+
Commands::Lock.run(path,
52+
print: args.includes?("--print"),
53+
update: args.includes?("--update")
54+
)
5255
when "outdated"
5356
Commands::Outdated.run(path, prereleases: args.includes?("--pre"))
5457
when "prune"

src/commands/lock.cr

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ require "../solver"
44
module Shards
55
module Commands
66
class Lock < Command
7-
def run(print = false)
7+
def run(print = false, update = false)
88
Shards.logger.info { "Resolving dependencies" }
99

1010
solver = Solver.new(spec)
11+
solver.locks = locks if !update && lockfile?
1112
solver.prepare(development: !Shards.production?)
1213

1314
if solution = solver.solve
@@ -26,7 +27,7 @@ module Shards
2627
end
2728

2829
private def to_lockfile(solution, io)
29-
io << "version: 1.1\n"
30+
io << "version: 1.0\n"
3031
io << "shards:\n"
3132

3233
solution.sort_by!(&.name).each do |rs|
@@ -41,7 +42,7 @@ module Shards
4142
io << " version: " << rs.version << '\n'
4243
end
4344

44-
puts
45+
io << '\n'
4546
end
4647
end
4748
end

src/solver.cr

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ module Shards
1010
version : String,
1111
commit : String?
1212

13-
alias Solution = Array(Result)
14-
15-
getter graph : Graph
13+
setter locks : Array(Dependency)?
1614

1715
def initialize(@spec : Spec)
1816
@graph = Graph.new
@@ -24,7 +22,7 @@ module Shards
2422
build_cnf_clauses(development)
2523
end
2624

27-
def solve : Solution?
25+
def solve : Array(Result)?
2826
distances = calculate_distances
2927

3028
solution = nil
@@ -50,7 +48,7 @@ module Shards
5048
end
5149

5250
private def to_result(proposal)
53-
solution = Solution.new
51+
solution = [] of Result
5452

5553
proposal.each do |str|
5654
next unless colon = str.index(':')
@@ -96,7 +94,7 @@ module Shards
9694
clause[0] =~ /^~(.+):(.+)$/
9795
a_name, a_version = $1, $2
9896

99-
spec = graph.packages[a_name].versions[a_version]
97+
spec = @graph.packages[a_name].versions[a_version]
10098
interest << "#{a_name}:"
10199
end
102100

@@ -143,7 +141,7 @@ module Shards
143141

144142
private def add_dependencies(negation, dependencies)
145143
dependencies.each do |d|
146-
versions = graph.resolve(d)
144+
versions = @graph.resolve(d)
147145

148146
if versions.empty?
149147
# FIXME: we couldn't resolve a constraint
@@ -163,18 +161,27 @@ module Shards
163161

164162
# Computes the distance for each version from a reference version, for
165163
# deciding the best solution.
166-
#
167-
# TODO: should be the distance from a given version or a range of
168-
# versions, not necessarily from the latest one (e.g. for
169-
# conservative updates).
170-
# TODO: consider adding some weight (e.g. to update some dependencies).
171164
private def calculate_distances
172165
distances = {} of String => Int32
173166
distances[@spec.name] = 0
174167

175-
graph.each do |pkg|
168+
@graph.each do |pkg|
169+
# reference is latest version by default:
170+
position = 0
171+
172+
if locked = @locks.try(&.find { |d| d.name == pkg.name })
173+
# determine position of locked version to use it as reference:
174+
pkg.each_version do |version, index|
175+
if version == locked.version
176+
position = index
177+
break
178+
end
179+
end
180+
end
181+
182+
# calculate distances to reference version:
176183
pkg.each_version do |version, index|
177-
distances["#{pkg.name}:#{version}"] = index
184+
distances["#{pkg.name}:#{version}"] = (position - index).abs
178185
end
179186
end
180187

0 commit comments

Comments
 (0)