Skip to content

Commit 04ef103

Browse files
authored
Dune Pins itself (#12583)
* Reproduce issue in #12381 The version of dune inside the opam repo is overriding the version of dune that is being used. That seems wrong. At least most of the time. Signed-off-by: Rudi Grinberg <[email protected]> * Remove [Resolved_package.set_url] Fuse it with [git_repo] since that is the only place where it's needed Signed-off-by: Rudi Grinberg <[email protected]> * fix(pkg): make dune pin itelf Automatically make dune pin itself. We're going to assume that the dune we're using right now is the one that will be used to run the build plan. Perhaps this behavior isn't always deired. We could imagine wanting to produce build plans for older or newer dunes. For now, this is a good default though. Addresses #12381 Signed-off-by: Rudi Grinberg <[email protected]>
1 parent 515f403 commit 04ef103

File tree

10 files changed

+171
-79
lines changed

10 files changed

+171
-79
lines changed

src/dune_pkg/dune_dep.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ let version =
66
let major, minor = Dune_lang.Stanza.latest_version in
77
OpamPackage.Version.of_string @@ sprintf "%d.%d" major minor
88
;;
9+
10+
let package = OpamPackage.create (Package_name.to_opam_package_name name) version
11+
let opam_file = OpamFile.OPAM.create package

src/dune_pkg/dune_dep.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
val name : Package_name.t
22
val version : OpamPackage.Version.t
3+
val package : OpamPackage.t
4+
val opam_file : OpamFile.OPAM.t

src/dune_pkg/opam_repo.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ let load_opam_package_from_dir ~(dir : Path.t) package =
134134
| false -> None
135135
| true ->
136136
let files_dir = Some (Paths.files_dir package) in
137-
Some (Resolved_package.local_fs package ~dir ~opam_file_path ~files_dir)
137+
Some (Resolved_package.local_fs package ~dir ~opam_file_path ~files_dir ~url:None)
138138
;;
139139

140140
let load_packages_from_git rev_store opam_packages =
@@ -151,7 +151,8 @@ let load_packages_from_git rev_store opam_packages =
151151
~opam_file:(Rev_store.File.path opam_file)
152152
~opam_file_contents
153153
rev
154-
~files_dir:(Some files_dir))
154+
~files_dir:(Some files_dir)
155+
~url:None)
155156
;;
156157

157158
let all_packages_in_dir_at_path ~dir ~path loc =

src/dune_pkg/opam_solver.ml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ module Context = struct
348348
let user_restrictions : t -> OpamPackage.Name.t -> OpamFormula.version_constraint option
349349
=
350350
fun t pkg ->
351+
(* This isn't really needed because we already pin dune, but it seems to
352+
help the error messages *)
351353
if Package_name.equal Dune_dep.name (Package_name.of_opam_package_name pkg)
352354
then Some (`Eq, t.dune_version)
353355
else None
@@ -1658,6 +1660,18 @@ let solve_lock_dir
16581660
~selected_depopts
16591661
~portable_lock_dir
16601662
=
1663+
let pinned_packages =
1664+
Package_name.Map.update pinned_packages Dune_dep.name ~f:(function
1665+
| None -> Some Resolved_package.dune
1666+
| Some p ->
1667+
let loc = Resolved_package.loc p in
1668+
User_error.raise
1669+
~loc
1670+
[ Pp.text
1671+
"Dune cannot be pinned. The currently running version is the only one that \
1672+
may be used"
1673+
])
1674+
in
16611675
let pinned_package_names = Package_name.Set.of_keys pinned_packages in
16621676
let stats_updater = Solver_stats.Updater.init () in
16631677
let context =

src/dune_pkg/pinned_package.ml

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -66,39 +66,38 @@ let resolve_package { Local_package.loc; url = loc_url, url; name; version; orig
6666
(Package_name.to_opam_package_name name)
6767
(Package_version.to_opam_package_version version)
6868
in
69-
let+ resolved_package =
70-
let* mount = Mount.of_opam_url loc_url url in
71-
let* opam_file_path, files_dir = discover_layout loc name mount in
72-
match Mount.backend mount with
73-
| Path dir ->
74-
Resolved_package.local_fs package ~dir ~opam_file_path ~files_dir |> Fiber.return
75-
| Git rev ->
76-
let+ opam_file_contents =
77-
(* CR-rgrinberg: not efficient to make such individual calls *)
78-
Mount.read mount opam_file_path
79-
>>| function
80-
| Some p -> p
81-
| None ->
82-
let files =
83-
match Path.Local.parent opam_file_path with
84-
| None -> []
85-
| Some parent ->
86-
Rev_store.At_rev.directory_entries rev parent ~recursive:false
87-
|> Rev_store.File.Set.to_list_map ~f:Rev_store.File.path
88-
in
89-
Code_error.raise
90-
~loc
91-
"unable to find file"
92-
[ "opam_file_path", Path.Local.to_dyn opam_file_path
93-
; "files", Dyn.list Path.Local.to_dyn files
94-
]
95-
in
96-
Resolved_package.git_repo
97-
package
98-
~opam_file:opam_file_path
99-
~opam_file_contents
100-
rev
101-
~files_dir
102-
in
103-
Resolved_package.set_url resolved_package url
69+
let* mount = Mount.of_opam_url loc_url url in
70+
let* opam_file_path, files_dir = discover_layout loc name mount in
71+
match Mount.backend mount with
72+
| Path dir ->
73+
Resolved_package.local_fs package ~dir ~opam_file_path ~files_dir ~url:(Some url)
74+
|> Fiber.return
75+
| Git rev ->
76+
let+ opam_file_contents =
77+
(* CR-rgrinberg: not efficient to make such individual calls *)
78+
Mount.read mount opam_file_path
79+
>>| function
80+
| Some p -> p
81+
| None ->
82+
let files =
83+
match Path.Local.parent opam_file_path with
84+
| None -> []
85+
| Some parent ->
86+
Rev_store.At_rev.directory_entries rev parent ~recursive:false
87+
|> Rev_store.File.Set.to_list_map ~f:Rev_store.File.path
88+
in
89+
Code_error.raise
90+
~loc
91+
"unable to find file"
92+
[ "opam_file_path", Path.Local.to_dyn opam_file_path
93+
; "files", Dyn.list Path.Local.to_dyn files
94+
]
95+
in
96+
Resolved_package.git_repo
97+
package
98+
~opam_file:opam_file_path
99+
~opam_file_contents
100+
rev
101+
~files_dir
102+
~url:(Some url)
104103
;;

src/dune_pkg/resolved_package.ml

Lines changed: 63 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,38 @@ type extra_files =
44
| Inside_files_dir of Path.t option
55
| Git_files of Path.Local.t option * Rev_store.At_rev.t
66

7-
type nonrec t =
7+
type rest =
88
{ opam_file : OpamFile.OPAM.t
99
; package : OpamPackage.t
1010
; extra_files : extra_files
1111
; loc : Loc.t
1212
; dune_build : bool
1313
}
1414

15-
let dune_build t = t.dune_build
16-
let loc t = t.loc
17-
let package t = t.package
18-
let opam_file t = t.opam_file
15+
type nonrec t =
16+
| Dune
17+
| Rest of rest
18+
19+
let dune = Dune
20+
21+
let dune_build = function
22+
| Dune -> false
23+
| Rest t -> t.dune_build
24+
;;
25+
26+
let loc = function
27+
| Dune -> Loc.none
28+
| Rest t -> t.loc
29+
;;
1930

20-
let set_url t url =
21-
let opam_file = OpamFile.OPAM.with_url (OpamFile.URL.create url) t.opam_file in
22-
{ t with opam_file }
31+
let package = function
32+
| Dune -> Dune_dep.package
33+
| Rest t -> t.package
34+
;;
35+
36+
let opam_file = function
37+
| Dune -> Dune_dep.opam_file
38+
| Rest t -> t.opam_file
2339
;;
2440

2541
let add_opam_package_to_opam_file package opam_file =
@@ -28,37 +44,44 @@ let add_opam_package_to_opam_file package opam_file =
2844
|> OpamFile.OPAM.with_name (OpamPackage.name package)
2945
;;
3046

31-
let read_opam_file package ~opam_file_path ~opam_file_contents =
32-
Opam_file.read_from_string_exn ~contents:opam_file_contents opam_file_path
33-
|> add_opam_package_to_opam_file package
47+
let read_opam_file package ~opam_file_path ~opam_file_contents ~url =
48+
let opam_file =
49+
Opam_file.read_from_string_exn ~contents:opam_file_contents opam_file_path
50+
|> add_opam_package_to_opam_file package
51+
in
52+
match url with
53+
| None -> opam_file
54+
| Some url -> OpamFile.OPAM.with_url (OpamFile.URL.create url) opam_file
3455
;;
3556

36-
let git_repo package ~opam_file ~opam_file_contents rev ~files_dir =
57+
let git_repo package ~opam_file ~opam_file_contents rev ~files_dir ~url =
3758
let opam_file_path = Path.of_local opam_file in
38-
let opam_file = read_opam_file package ~opam_file_path ~opam_file_contents in
59+
let opam_file = read_opam_file package ~opam_file_path ~opam_file_contents ~url in
3960
let loc = Loc.in_file opam_file_path in
40-
{ dune_build = false
41-
; loc
42-
; package
43-
; opam_file
44-
; extra_files = Git_files (files_dir, rev)
45-
}
61+
Rest
62+
{ dune_build = false
63+
; loc
64+
; package
65+
; opam_file
66+
; extra_files = Git_files (files_dir, rev)
67+
}
4668
;;
4769

48-
let local_fs package ~dir ~opam_file_path ~files_dir =
70+
let local_fs package ~dir ~opam_file_path ~files_dir ~url =
4971
let opam_file_path = Path.append_local dir opam_file_path in
5072
let files_dir = Option.map files_dir ~f:(Path.append_local dir) in
5173
let opam_file =
5274
let opam_file_contents = Io.read_file ~binary:true opam_file_path in
53-
read_opam_file package ~opam_file_path ~opam_file_contents
75+
read_opam_file package ~opam_file_path ~opam_file_contents ~url
5476
in
5577
let loc = Loc.in_file opam_file_path in
56-
{ dune_build = false
57-
; loc
58-
; package
59-
; extra_files = Inside_files_dir files_dir
60-
; opam_file
61-
}
78+
Rest
79+
{ dune_build = false
80+
; loc
81+
; package
82+
; extra_files = Inside_files_dir files_dir
83+
; opam_file
84+
}
6285
;;
6386

6487
(* Scan a path recursively down retrieving a list of all files together with their
@@ -92,18 +115,26 @@ let local_package ~command_source loc opam_file opam_package =
92115
in
93116
let opam_file = add_opam_package_to_opam_file opam_package opam_file in
94117
let package = OpamFile.OPAM.package opam_file in
95-
{ dune_build; opam_file; package; loc; extra_files = Inside_files_dir None }
118+
Rest { dune_build; opam_file; package; loc; extra_files = Inside_files_dir None }
96119
;;
97120

98121
open Fiber.O
99122

100123
let get_opam_package_files resolved_packages =
101124
let indexed = List.mapi resolved_packages ~f:(fun i w -> i, w) |> Int.Map.of_list_exn in
102125
let from_dirs, from_git =
103-
Int.Map.partition_map indexed ~f:(fun (resolved_package : t) ->
104-
match resolved_package.extra_files with
105-
| Git_files (files_dir, rev) -> Right (files_dir, rev)
106-
| Inside_files_dir dir -> Left dir)
126+
let _dune, without_dune =
127+
Int.Map.partition_map indexed ~f:(function
128+
| Dune -> Left ()
129+
| Rest t -> Right t)
130+
in
131+
let dirs, git =
132+
Int.Map.partition_map without_dune ~f:(fun (resolved_package : rest) ->
133+
match resolved_package.extra_files with
134+
| Git_files (files_dir, rev) -> Right (files_dir, rev)
135+
| Inside_files_dir dir -> Left dir)
136+
in
137+
dirs, git
107138
in
108139
let+ from_git =
109140
if Int.Map.is_empty from_git

src/dune_pkg/resolved_package.mli

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,24 @@ type t
55
val package : t -> OpamPackage.t
66
val opam_file : t -> OpamFile.OPAM.t
77
val loc : t -> Loc.t
8-
val set_url : t -> OpamUrl.t -> t
98
val dune_build : t -> bool
9+
val dune : t
1010

1111
val git_repo
1212
: OpamPackage.t
1313
-> opam_file:Path.Local.t
1414
-> opam_file_contents:string
1515
-> Rev_store.At_rev.t
1616
-> files_dir:Path.Local.t option
17+
-> url:OpamUrl.t option
1718
-> t
1819

1920
val local_fs
2021
: OpamPackage.t
2122
-> dir:Path.t
2223
-> opam_file_path:Path.Local.t
2324
-> files_dir:Path.Local.t option
25+
-> url:OpamUrl.t option
2426
-> t
2527

2628
val local_package

test/blackbox-tests/test-cases/pkg/implicit-dune-constraint.t

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ dependency.
66
$ . ./helpers.sh
77
$ mkrepo
88

9-
$ mkpkg dune 3.11.0 <<EOF
10-
> EOF
11-
129
$ test() {
1310
> mkpkg foo <<EOF
1411
> depends: [ "dune" {<= "$1"} ]
@@ -23,12 +20,17 @@ dependency.
2320
Selected candidates: foo.0.0.1 x.dev
2421
- dune -> (problem)
2522
User requested = 3.XX
23+
foo 0.0.1 requires <= 2.0.0
2624
Rejected candidates:
27-
dune.3.XX.0: Incompatible with restriction: = 3.XX
25+
dune.3.XX: Incompatible with restriction: <= 2.0.0
2826
$ test "4.0.0"
2927
Solution for dune.lock:
3028
- foo.0.0.1
3129

30+
$ test "4.0.0" 2>&1 | sed -E 's/3.[0-9]+/3.XX/g'
31+
Solution for dune.lock:
32+
- foo.0.0.1
33+
3234
Create a fake project and ensure `dune` can be used as a dependency:
3335
$ cat > dune-project <<EOF
3436
> (lang dune 3.13)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
Pinning dune itself
2+
3+
$ . ../helpers.sh
4+
5+
$ mkrepo
6+
$ add_mock_repo_if_needed
7+
8+
# CR-someday rgrinberg: ideally, this source shouldn't be necessary and we
9+
# should disqualify this pin without resolving any sources
10+
11+
$ mkdir _extra_source
12+
$ cat >_extra_source/dune-project <<EOF
13+
> (lang dune 3.12)
14+
> (package (name dune))
15+
> EOF
16+
17+
$ cat >dune-project <<EOF
18+
> (lang dune 3.13)
19+
> (pin
20+
> (url "file://$PWD/_extra_source")
21+
> (package (name dune)))
22+
> (package
23+
> (name main))
24+
> EOF
25+
26+
For now, pinning dune is not allowed:
27+
28+
$ dune pkg lock
29+
File "dune-project", line 4, characters 1-22:
30+
4 | (package (name dune)))
31+
^^^^^^^^^^^^^^^^^^^^^
32+
Error: Dune cannot be pinned. The currently running version is the only one
33+
that may be used
34+
[1]

test/blackbox-tests/test-cases/pkg/unsatisfied-version-constraint-on-dune.t

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,12 @@ project:
2222

2323
Solve the dependencies:
2424
$ dune pkg lock 2>&1 | sed -E 's/"3.[0-9]+"/"3.XX"/'
25-
Error: The current version of Dune does not satisfy the version constraints
26-
for Dune in this project's dependencies.
27-
Details:
28-
Found version "3.XX" of package "dune" which doesn't satisfy the required
29-
version constraint "< 3.0"
25+
Error: Unable to solve dependencies for the following lock directories:
26+
Lock directory dune.lock:
27+
Couldn't solve the package dependency formula.
28+
Selected candidates: foo.dev
29+
- dune -> (problem)
30+
User requested = 3.21
31+
foo dev requires < 3.0
32+
Rejected candidates:
33+
dune.3.21: Incompatible with restriction: < 3.0

0 commit comments

Comments
 (0)