@@ -1148,11 +1148,14 @@ type missing_dependency =
11481148 ; loc : Loc .t
11491149 }
11501150
1151- (* [validate_packages packages] returns
1151+ (* [validate_packages packages ~external_packages ] returns
11521152 [Error (`Missing_dependencies missing_dependencies)] where
11531153 [missing_dependencies] is a non-empty list with an element for each package
1154- dependency which doesn't have a corresponding entry in [packages]. *)
1155- let validate_packages packages =
1154+ dependency which doesn't have a corresponding entry in [packages] and is
1155+ not in [external_packages]. The [external_packages] set names dependency
1156+ targets that callers vouch for outside the lockdir (e.g. workspace
1157+ packages whose install entries are materialised by the build path). *)
1158+ let validate_packages packages ~external_packages =
11561159 let missing_dependencies =
11571160 Packages. to_pkg_list packages
11581161 |> List. concat_map ~f: (fun (dependant_package : Pkg.t ) ->
@@ -1163,6 +1166,7 @@ let validate_packages packages =
11631166 if
11641167 Package_name.Map. mem packages depend.name
11651168 || Package_name. equal depend.name Dune_dep. name
1169+ || Package_name.Set. mem external_packages depend.name
11661170 then None
11671171 else Some { dependant_package; dependency = depend.name; loc = depend.loc })))
11681172 in
@@ -1184,7 +1188,11 @@ let create_latest_version
11841188 Package_name.Map. map packages ~f: (fun (pkg : Pkg.t ) ->
11851189 Package_version.Map. singleton pkg.info.version pkg)
11861190 in
1187- (match validate_packages packages with
1191+ (* The solver rejects workspace dependencies, so a well-formed solver
1192+ output should never contain references to packages outside the
1193+ lockdir. We pass [external_packages:empty] here so this assert catches
1194+ any solver bug that lets such a reference slip through. *)
1195+ (match validate_packages packages ~external_packages: Package_name.Set. empty with
11881196 | Ok () -> ()
11891197 | Error (`Missing_dependencies missing_dependencies ) ->
11901198 List. map missing_dependencies ~f: (fun { dependant_package; dependency; loc = _ } ->
@@ -1658,40 +1666,6 @@ struct
16581666 package_name
16591667 ;;
16601668
1661- let check_packages packages ~lock_dir_path =
1662- match validate_packages packages with
1663- | Ok () -> Ok ()
1664- | Error (`Missing_dependencies missing_dependencies ) ->
1665- List. iter missing_dependencies ~f: (fun { dependant_package; dependency; loc } ->
1666- User_message. prerr
1667- (User_message. make
1668- ~loc
1669- [ Pp. textf
1670- " The package %S depends on the package %S, but %S does not appear in \
1671- the lockdir %s."
1672- (Package_name. to_string dependant_package.info.name)
1673- (Package_name. to_string dependency)
1674- (Package_name. to_string dependency)
1675- (Path. to_string_maybe_quoted lock_dir_path)
1676- ]));
1677- Error
1678- (User_error. make
1679- ~hints:
1680- [ Pp. concat
1681- ~sep: Pp. space
1682- [ Pp. text
1683- " This could indicate that the lockdir is corrupted. Delete it and \
1684- then regenerate it by running:"
1685- ; User_message. command " dune pkg lock"
1686- ]
1687- ]
1688- [ Pp. textf
1689- " At least one package dependency is itself not present as a package in \
1690- the lockdir %s."
1691- (Path. to_string_maybe_quoted lock_dir_path)
1692- ])
1693- ;;
1694-
16951669 let load lock_dir_path =
16961670 let event =
16971671 Dune_trace. (
@@ -1735,25 +1709,15 @@ struct
17351709 pkg)
17361710 >> | Packages. of_pkg_list
17371711 in
1738- let result =
1739- check_packages packages ~lock_dir_path
1740- |> Result. map ~f: (fun () ->
1741- { version
1742- ; dependency_hash
1743- ; packages
1744- ; ocaml
1745- ; repos
1746- ; expanded_solver_variable_bindings
1747- ; solved_for_platforms
1748- })
1749- in
17501712 Option. iter (Dune_trace. global () ) ~f: (fun trace -> Dune_trace.Out. finish trace event);
1751- result
1752- ;;
1753-
1754- let load_exn lock_dir_path =
1755- let open Io.O in
1756- load lock_dir_path >> | User_error. ok_exn
1713+ { version
1714+ ; dependency_hash
1715+ ; packages
1716+ ; ocaml
1717+ ; repos
1718+ ; expanded_solver_variable_bindings
1719+ ; solved_for_platforms
1720+ }
17571721 ;;
17581722end
17591723
@@ -1771,8 +1735,53 @@ module Load_immediate = Make_load (struct
17711735 let with_lexbuf_from_file = Io. with_lexbuf_from_file
17721736 end )
17731737
1774- let read_disk = Load_immediate. load
1775- let read_disk_exn = Load_immediate. load_exn
1738+ (* Verify every dependency edge in [packages] resolves to a known target:
1739+ either another package in the lockdir, dune itself, or a name in
1740+ [external_packages] (typically workspace packages whose install entries
1741+ are materialised outside the lockdir). *)
1742+ let check_packages packages ~lock_dir_path ~external_packages =
1743+ match validate_packages packages ~external_packages with
1744+ | Ok () -> Ok ()
1745+ | Error (`Missing_dependencies missing_dependencies ) ->
1746+ List. iter missing_dependencies ~f: (fun { dependant_package; dependency; loc } ->
1747+ User_message. prerr
1748+ (User_message. make
1749+ ~loc
1750+ [ Pp. textf
1751+ " The package %S depends on the package %S, but %S does not appear in the \
1752+ lockdir %s."
1753+ (Package_name. to_string dependant_package.info.name)
1754+ (Package_name. to_string dependency)
1755+ (Package_name. to_string dependency)
1756+ (Path. to_string_maybe_quoted lock_dir_path)
1757+ ]));
1758+ Error
1759+ (User_error. make
1760+ ~hints:
1761+ [ Pp. concat
1762+ ~sep: Pp. space
1763+ [ Pp. text
1764+ " This could indicate that the lockdir is corrupted. Delete it and \
1765+ then regenerate it by running:"
1766+ ; User_message. command " dune pkg lock"
1767+ ]
1768+ ]
1769+ [ Pp. textf
1770+ " At least one package dependency is itself not present as a package in the \
1771+ lockdir %s."
1772+ (Path. to_string_maybe_quoted lock_dir_path)
1773+ ])
1774+ ;;
1775+
1776+ let read_disk lock_dir_path ~external_packages =
1777+ let t = Load_immediate. load lock_dir_path in
1778+ check_packages t.packages ~lock_dir_path ~external_packages
1779+ |> Result. map ~f: (fun () -> t)
1780+ ;;
1781+
1782+ let read_disk_exn lock_dir_path ~external_packages =
1783+ read_disk lock_dir_path ~external_packages |> User_error. ok_exn
1784+ ;;
17761785
17771786let transitive_dependency_closure t ~platform start =
17781787 let missing_packages =
0 commit comments