1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
|
open Import
module Lock_dir = Dune_pkg.Lock_dir
module Solver_env = Dune_pkg.Solver_env
module Package_variable_name = Dune_lang.Package_variable_name
module Variable_value = Dune_pkg.Variable_value
let solver_env
~solver_env_from_current_system
~solver_env_from_context
~unset_solver_vars_from_context
=
let solver_env =
[ solver_env_from_current_system; solver_env_from_context ]
|> List.filter_opt
|> List.fold_left ~init:Solver_env.with_defaults ~f:Solver_env.extend
in
match unset_solver_vars_from_context with
| None -> solver_env
| Some unset_solver_vars -> Solver_env.unset_multi solver_env unset_solver_vars
;;
let poll_solver_env_from_current_system () =
Dune_pkg.Sys_poll.make ~path:(Env_path.path Stdune.Env.initial)
|> Dune_pkg.Sys_poll.solver_env_from_current_system
;;
let get_lock_dir_from_context ~lock_dir_path =
Memo.run
@@
let open Memo.O in
let+ workspace = Workspace.workspace () in
Workspace.find_lock_dir workspace lock_dir_path
;;
let get_solver_env_from_context ~lock_dir_path =
let open Fiber.O in
let+ lock_dir = get_lock_dir_from_context ~lock_dir_path in
Option.bind lock_dir ~f:(fun lock_dir -> lock_dir.solver_env)
;;
let get_unset_solver_vars_from_context ~lock_dir_path =
let open Fiber.O in
let+ lock_dir = get_lock_dir_from_context ~lock_dir_path in
Option.bind lock_dir ~f:(fun lock_dir -> lock_dir.unset_solver_vars)
;;
let solver_env_from_system_and_context ~lock_dir_path =
let open Fiber.O in
let+ solver_env_from_current_system =
poll_solver_env_from_current_system () >>| Option.some
and+ solver_env_from_context = get_solver_env_from_context ~lock_dir_path
and+ unset_solver_vars_from_context =
get_unset_solver_vars_from_context ~lock_dir_path
in
solver_env
~solver_env_from_current_system
~solver_env_from_context
~unset_solver_vars_from_context
;;
module Version_preference = struct
include Dune_pkg.Version_preference
let term =
let all_strings = List.map all_by_string ~f:fst in
let doc =
sprintf
"Whether to prefer the newest compatible version of a package or the oldest \
compatible version of packages while solving dependencies. This overrides any \
setting in the current workspace. The default is %s."
(to_string default)
in
let docv = String.concat ~sep:"|" all_strings |> sprintf "(%s)" in
Arg.(
value
& opt (some (enum all_by_string)) None
& info [ "version-preference" ] ~doc ~docv)
;;
let choose ~from_arg ~from_context =
match from_arg, from_context with
| Some from_arg, _ -> from_arg
| None, Some from_context -> from_context
| None, None -> default
;;
end
let repositories_of_workspace (workspace : Workspace.t) =
List.map workspace.repos ~f:(fun repo ->
Dune_pkg.Pkg_workspace.Repository.name repo, repo)
|> Dune_pkg.Pkg_workspace.Repository.Name.Map.of_list_exn
;;
let constraints_of_workspace (workspace : Workspace.t) ~lock_dir_path =
match Workspace.find_lock_dir workspace lock_dir_path with
| None -> []
| Some lock_dir -> lock_dir.constraints
;;
let depopts_of_workspace (workspace : Workspace.t) ~lock_dir_path =
match Workspace.find_lock_dir workspace lock_dir_path with
| None -> []
| Some lock_dir -> lock_dir.depopts |> List.map ~f:snd
;;
let repositories_of_lock_dir workspace ~lock_dir_path =
match Workspace.find_lock_dir workspace lock_dir_path with
| Some lock_dir -> lock_dir.repositories
| None ->
List.map workspace.repos ~f:(fun repo ->
let name = Dune_pkg.Pkg_workspace.Repository.name repo in
let loc = Loc.none in
loc, name)
;;
let unset_solver_vars_of_workspace workspace ~lock_dir_path =
let open Option.O in
let* lock_dir = Workspace.find_lock_dir workspace lock_dir_path in
lock_dir.unset_solver_vars
;;
let get_repos repos ~repositories =
let module Repository = Dune_pkg.Pkg_workspace.Repository in
repositories
|> Fiber.parallel_map ~f:(fun (loc, name) ->
match Repository.Name.Map.find repos name with
| None ->
User_error.raise
~loc
[ Pp.textf "Repository '%s' is not a known repository"
@@ Repository.Name.to_string name
]
| Some repo ->
let loc, opam_url = Repository.opam_url repo in
let module Opam_repo = Dune_pkg.Opam_repo in
(match Dune_pkg.OpamUrl.classify opam_url loc with
| `Git -> Opam_repo.of_git_repo loc opam_url
| `Path path -> Fiber.return @@ Opam_repo.of_opam_repo_dir_path loc path
| `Archive ->
User_error.raise
~loc
[ Pp.textf "Repositories stored in archives (%s) are currently unsupported"
@@ OpamUrl.to_string opam_url
]))
;;
let find_local_packages =
let open Memo.O in
Dune_rules.Dune_load.packages ()
>>| Package.Name.Map.map ~f:Dune_pkg.Local_package.of_package
;;
let pp_package { Lock_dir.Pkg.info = { Lock_dir.Pkg_info.name; version; avoid; _ }; _ } =
let warn =
if avoid
then Pp.tag User_message.Style.Warning (Pp.text " (this version should be avoided)")
else Pp.nop
in
let open Pp.O in
Pp.verbatim
(Package_name.to_string name ^ "." ^ Dune_pkg.Package_version.to_string version)
++ warn
;;
let pp_packages packages = Pp.enumerate packages ~f:pp_package
module Lock_dirs_arg = struct
type t =
| All
| Selected of Path.Source.t list
let all = All
let term =
Common.one_of
(let+ arg =
Arg.(
value
& pos_all string []
& info
[]
~docv:"LOCKDIRS"
~doc:
"Lock directories to check for outdated packages. Defaults to dune.lock.")
in
Selected (List.map arg ~f:Path.Source.of_string))
(let+ _all =
Arg.(
value
& flag
& info
[ "all" ]
~doc:"Check all lock directories in the workspace for outdated packages.")
in
All)
;;
let lock_dirs_of_workspace t (workspace : Workspace.t) =
let workspace_lock_dirs =
Lock_dir.default_path
:: List.map workspace.lock_dirs ~f:(fun (lock_dir : Workspace.Lock_dir.t) ->
lock_dir.path)
|> Path.Source.Set.of_list
|> Path.Source.Set.to_list
in
match t with
| All -> workspace_lock_dirs
| Selected [] -> [ Lock_dir.default_path ]
| Selected chosen_lock_dirs ->
let workspace_lock_dirs_set = Path.Source.Set.of_list workspace_lock_dirs in
let chosen_lock_dirs_set = Path.Source.Set.of_list chosen_lock_dirs in
if Path.Source.Set.is_subset chosen_lock_dirs_set ~of_:workspace_lock_dirs_set
then chosen_lock_dirs
else (
let unknown_lock_dirs =
Path.Source.Set.diff chosen_lock_dirs_set workspace_lock_dirs_set
|> Path.Source.Set.to_list
in
let f x = Path.pp (Path.source x) in
User_error.raise
[ Pp.text
"The following directories are not lock directories in this workspace:"
; Pp.enumerate unknown_lock_dirs ~f
; Pp.text "This workspace contains the following lock directories:"
; Pp.enumerate workspace_lock_dirs ~f
])
;;
end
|