Skip to content

Commit 968e255

Browse files
authored
pkg: relock ocamlformat when version changes (#12605)
The .ocamlformat file can contain the version of ocamlformat which a project uses for autoformatting. Previously this file was used to determine which version of ocamlformat to install initially, but changes to the version specified in .ocamlformat did not cause dune to relock the tool with the new version, leading to a mismatch between the specified and installed versions of ocamlformat within a project. This change allows dune to detect when the specified and locked versions of ocamlformat differ, and relocks (and re-installs) ocamlformat in this case. Signed-off-by: Stephen Sherratt <[email protected]>
1 parent 13d972e commit 968e255

File tree

3 files changed

+137
-29
lines changed

3 files changed

+137
-29
lines changed

bin/lock_dev_tool.ml

Lines changed: 70 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -185,34 +185,51 @@ let lockdir_status dev_tool =
185185
(match Lock_dir.read_disk dev_tool_lock_dir with
186186
| Error _ -> Memo.return `No_lockdir
187187
| Ok { packages; _ } ->
188-
(match Dune_pkg.Dev_tool.needs_to_build_with_same_compiler_as_project dev_tool with
189-
| false -> Memo.return `Lockdir_ok
190-
| true ->
191-
let* platform =
192-
Pkg.Pkg_common.poll_solver_env_from_current_system ()
193-
|> Memo.of_reproducible_fiber
194-
in
195-
let packages = Lock_dir.Packages.pkgs_on_platform_by_name packages ~platform in
196-
(match Package_name.Map.find packages compiler_package_name with
197-
| None -> Memo.return `No_compiler_lockfile_in_lockdir
198-
| Some { info; _ } ->
199-
let+ ocaml_compiler_version = locked_ocaml_compiler_version () in
200-
(match Package_version.equal info.version ocaml_compiler_version with
201-
| true -> `Lockdir_ok
202-
| false ->
203-
`Dev_tool_needs_to_be_relocked_because_project_compiler_version_changed
204-
(User_message.make
205-
[ Pp.textf
206-
"The version of the compiler package (%S) in this project's \
207-
lockdir has changed to %s (formerly the compiler version was \
208-
%s). The dev-tool %S will be re-locked and rebuilt with this \
209-
version of the compiler."
210-
(Package_name.to_string compiler_package_name)
211-
(Package_version.to_string ocaml_compiler_version)
212-
(Package_version.to_string info.version)
213-
(Dune_pkg.Dev_tool.package_name dev_tool
214-
|> Package_name.to_string)
215-
])))))
188+
let* platform =
189+
Pkg.Pkg_common.poll_solver_env_from_current_system ()
190+
|> Memo.of_reproducible_fiber
191+
in
192+
let packages = Lock_dir.Packages.pkgs_on_platform_by_name packages ~platform in
193+
let package_name = Dune_pkg.Dev_tool.package_name dev_tool in
194+
(match Package_name.Map.find packages package_name with
195+
| None ->
196+
Memo.return
197+
(`Lockdir_missing_entry_for_tool
198+
(User_message.make
199+
[ Pp.textf
200+
"The lock directory for the tool %S exists but does not contain a \
201+
lockfile for the package %S. This may indicate that the lock \
202+
directory has been tampered with. Please avoid making manual \
203+
changes to tool lock directories. The tool will now be relocked."
204+
(Dune_pkg.Dev_tool.exe_name dev_tool)
205+
(Package_name.to_string package_name)
206+
]))
207+
| Some pkg ->
208+
(match
209+
Dune_pkg.Dev_tool.needs_to_build_with_same_compiler_as_project dev_tool
210+
with
211+
| false -> Memo.return (`Lockdir_ok_with_tool_pkg pkg)
212+
| true ->
213+
(match Package_name.Map.find packages compiler_package_name with
214+
| None -> Memo.return `No_compiler_lockfile_in_lockdir
215+
| Some { info; _ } ->
216+
let+ ocaml_compiler_version = locked_ocaml_compiler_version () in
217+
(match Package_version.equal info.version ocaml_compiler_version with
218+
| true -> `Lockdir_ok_with_tool_pkg pkg
219+
| false ->
220+
`Dev_tool_needs_to_be_relocked_because_project_compiler_version_changed
221+
(User_message.make
222+
[ Pp.textf
223+
"The version of the compiler package (%S) in this project's \
224+
lockdir has changed to %s (formerly the compiler version \
225+
was %s). The dev-tool %S will be re-locked and rebuilt with \
226+
this version of the compiler."
227+
(Package_name.to_string compiler_package_name)
228+
(Package_version.to_string ocaml_compiler_version)
229+
(Package_version.to_string info.version)
230+
(Dune_pkg.Dev_tool.package_name dev_tool
231+
|> Package_name.to_string)
232+
]))))))
216233
;;
217234

218235
(* [lock_dev_tool_at_version dev_tool version] generates the lockdir for the
@@ -224,7 +241,28 @@ let lock_dev_tool_at_version dev_tool version =
224241
let* need_to_solve =
225242
lockdir_status dev_tool
226243
>>| function
227-
| `Lockdir_ok -> false
244+
| `Lockdir_ok_with_tool_pkg (pkg : Dune_pkg.Lock_dir.Pkg.t) ->
245+
(match version with
246+
| None -> false
247+
| Some version ->
248+
(* If this function was passed a specific version, and the dev
249+
tool's lockfile contains a different version from the specified
250+
version, regenerate the lockdir. *)
251+
let different_version_currently_locked =
252+
not (Package_version.equal pkg.info.version version)
253+
in
254+
if different_version_currently_locked
255+
then
256+
Console.print
257+
[ Pp.textf
258+
"The lock directory for the tool %S exists but contains a solution for \
259+
%s of the tool, whereas version %s now needs to be installed. The tool \
260+
will now be re-locked."
261+
(Dune_pkg.Dev_tool.exe_name dev_tool)
262+
(Package_version.to_string pkg.info.version)
263+
(Package_version.to_string version)
264+
];
265+
different_version_currently_locked)
228266
| `No_lockdir -> true
229267
| `No_compiler_lockfile_in_lockdir ->
230268
Console.print
@@ -237,6 +275,9 @@ let lock_dev_tool_at_version dev_tool version =
237275
| `Dev_tool_needs_to_be_relocked_because_project_compiler_version_changed message ->
238276
Console.print_user_message message;
239277
true
278+
| `Lockdir_missing_entry_for_tool message ->
279+
User_warning.emit_message message;
280+
true
240281
in
241282
if need_to_solve
242283
then
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
When installing a dev tool which already has a lockdir, detect the case where
2+
the tool's lockfile is absent from the lockdir and relock.
3+
4+
$ . ./helpers.sh
5+
$ mkrepo
6+
7+
Make a fake ocamlformat package
8+
$ make_fake_ocamlformat "0.26.0"
9+
$ make_ocamlformat_opam_pkg "0.26.0"
10+
11+
$ make_project_with_dev_tool_lockdir
12+
13+
Install ocamlformat once to generate the lockdir.
14+
$ dune tools install ocamlformat
15+
Solution for dev-tools.locks/ocamlformat:
16+
- ocamlformat.0.26.0
17+
18+
Delete ocamlformat's lockfile.
19+
$ rm dev-tools.locks/ocamlformat/ocamlformat.pkg
20+
21+
Reinstall ocamlformat.
22+
$ dune tools install ocamlformat
23+
Warning: The lock directory for the tool "ocamlformat" exists but does not
24+
contain a lockfile for the package "ocamlformat". This may indicate that the
25+
lock directory has been tampered with. Please avoid making manual changes to
26+
tool lock directories. The tool will now be relocked.
27+
Solution for dev-tools.locks/ocamlformat:
28+
- ocamlformat.0.26.0
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
When the version in .ocamlformat changes, automatically relock ocamlformat with
2+
the new version.
3+
4+
$ . ./helpers.sh
5+
$ mkrepo
6+
7+
$ make_fake_ocamlformat "0.26.0"
8+
$ echo ocamlformat-0.26.0.tar > fake-curls
9+
$ make_ocamlformat_opam_pkg "0.26.0" 1
10+
11+
$ make_fake_ocamlformat "0.27.0"
12+
$ echo ocamlformat-0.27.0.tar >> fake-curls
13+
$ make_ocamlformat_opam_pkg "0.27.0" 2
14+
15+
Make dune-project that uses the mocked dev-tool opam-reposiotry.
16+
$ make_project_with_dev_tool_lockdir
17+
18+
Create .ocamlformat file
19+
$ cat > .ocamlformat <<EOF
20+
> version = 0.26.0
21+
> EOF
22+
23+
Install ocamlformat. 0.26.0 should be installed because that's the version in .ocamlformat.
24+
$ dune tools install ocamlformat
25+
Solution for dev-tools.locks/ocamlformat:
26+
- ocamlformat.0.26.0
27+
28+
Change the version in .ocamlformat.
29+
$ cat > .ocamlformat <<EOF
30+
> version = 0.27.0
31+
> EOF
32+
33+
Install ocamlformat again. Dune should detect that the version has changed and relock:
34+
$ dune tools install ocamlformat
35+
The lock directory for the tool "ocamlformat" exists but contains a solution
36+
for 0.26.0 of the tool, whereas version 0.27.0 now needs to be installed. The
37+
tool will now be re-locked.
38+
Solution for dev-tools.locks/ocamlformat:
39+
- ocamlformat.0.27.0

0 commit comments

Comments
 (0)