package opam-client
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Client library for opam 2.6
Install
dune-project
Dependency
Authors
-
David Allsopp
-
VVincent Bernardoff <vb@luminar.eu.org>
-
RRaja Boujbel <raja.boujbel@ocamlpro.com>
-
KKate Deplaix <kit-ty-kate@exn.st>
-
RRoberto Di Cosmo <roberto@dicosmo.org>
-
TThomas Gazagnaire <thomas@gazagnaire.org>
-
LLouis Gesbert <louis.gesbert@ocamlpro.com>
-
FFabrice Le Fessant <Fabrice.Le_fessant@inria.fr>
-
AAnil Madhavapeddy <anil@recoil.org>
-
GGuillem Rieu <guillem.rieu@ocamlpro.com>
-
RRalf Treinen <ralf.treinen@pps.jussieu.fr>
-
FFrederic Tuong <tuong@users.gforge.inria.fr>
Maintainers
Sources
2.6.1.tar.gz
md5=5bf39a9d5668d6140018c8fb79354fb8
sha512=c5b0ec8e87388278ee2a560f1b4c53523619d77c42228f09852f3b16a4cba3221fc0ceee997b88c7d44987e90c4f7801430fca0d2dccc3a4d64b0a8713d0384a
doc/src/opam-client/opamTreeCommand.ml.html
Source file opamTreeCommand.ml
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 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455(**************************************************************************) (* *) (* Copyright 2012-2019 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved. This file is distributed under the terms of the *) (* GNU Lesser General Public License version 2.1, with the special *) (* exception on linking described in the file LICENSE. *) (* *) (**************************************************************************) open OpamTypes open OpamStateTypes type deps = private [`deps] type revdeps = private [`revdeps] type 'a node = | Root of package | Dependency : { package: package; satisfies: condition option; is_dup: bool; } -> deps node | Requirement : { package: package; demands: condition option; is_dup: bool; } -> revdeps node module Tree = OpamConsole.Tree type 'a forest = 'a Tree.t list type tree_filter = | Roots_from | Leads_to type mode = | Deps | ReverseDeps type resulting_forest = | DepsForest of deps node forest | RevdepsForest of revdeps node forest (** Forest building *) let build_condition_map tog st = let { OpamListCommand.recursive = _; depopts = _; build; post; test; dev_setup; doc; dev; } = tog in let partial_env = let vars = [ "build", build; "post", post; "dev", dev; "with-doc", doc; "with-test", test; "with-dev-setup", dev_setup; ] |> List.map (fun (v, f) -> v, if f then None else Some (B false)) in fun var -> OpamStd.List.find_map_opt (fun (v,c) -> if String.equal v (OpamVariable.Full.to_string var) then c else None) vars in OpamPackage.Set.fold (fun package cmap -> let map = OpamSwitchState.opam st package |> OpamFile.OPAM.depends (* remove any irrelevant variables to simplify the output *) |> OpamFilter.partial_filter_formula partial_env |> OpamFormula.formula_to_dnf |> OpamStd.List.find_map_opt (fun cnj -> let is_valid, result = cnj (* filter out non-installed dependencies *) |> List.filter (fun (name, _) -> OpamSwitchState.is_name_installed st name) |> List.fold_left_map (fun is_valid orig -> if not is_valid then is_valid, orig else let filtered = OpamFilter.filter_deps ~build ~post ~doc ~test ~dev_setup ~dev ~default:true (Atom orig) in match filtered with | Atom (name, _) -> let package = OpamSwitchState.find_installed_package_by_name st name in let is_valid = OpamFormula.eval (fun atom -> OpamFormula.check atom package) (OpamFormula.to_atom_formula filtered) in is_valid, orig | _ -> false, orig (* should be impossible *) ) true in if is_valid then Some result else None ) |> OpamStd.Option.default [] |> OpamPackage.Name.Map.of_list in cmap |> OpamPackage.Map.add package map ) st.installed OpamPackage.Map.empty let is_root graph p = OpamSolver.PkgGraph.in_degree graph p = 0 let is_leaf graph p = OpamSolver.PkgGraph.out_degree graph p = 0 let cut_leaves (mode: [ `succ | `pred]) ~names ~root st graph = let fold, is_final = match mode with | `succ -> OpamSolver.PkgGraph.fold_succ, is_leaf graph | `pred -> OpamSolver.PkgGraph.fold_pred, is_root graph in (* compute the packages which are connected to one of the `names` *) let rec go package set = fold (fun p ps -> if OpamPackage.Set.mem p ps then ps else let ps = OpamPackage.Set.add p ps in if not (is_final p) then go p ps else ps ) graph package set in let packages = names |> OpamPackage.Set.fold go names in (* cut leaves not belonging to the packages *) OpamPackage.Set.diff st.installed packages |> OpamPackage.Set.iter (OpamSolver.PkgGraph.remove_vertex graph); (* return the new roots and the new graph *) OpamPackage.Set.inter root packages, graph let build_deps_forest st universe tog filter names = let { OpamListCommand.build; post; _ } = tog in let root, graph = let graph = OpamSolver.dependency_graph ~depopts:false ~build ~post ~installed:true ~unavailable:false universe in let root = st.installed |> OpamPackage.Set.filter (is_root graph) in match OpamPackage.Set.is_empty names, filter with | false, Roots_from -> names, graph | false, Leads_to -> cut_leaves `pred ~names ~root st graph | true, _ -> root, graph in let condition_map = build_condition_map tog st in let rec build visited package node = if visited |> OpamPackage.Set.mem package then let node = match node with | Root p -> Root p (* but impossible *) | Dependency x -> Dependency { x with is_dup = true } in visited, Tree.create node else let visited = visited |> OpamPackage.Set.add package in let conditions = condition_map |> OpamPackage.Map.find package in let succ = OpamSolver.PkgGraph.succ graph package in let visited, children = List.fold_left_map (fun visited package -> let satisfies = OpamPackage.(Name.Map.find_opt package.name) conditions in let child_node = Dependency { package; satisfies; is_dup = false } in build visited package child_node ) visited succ in visited, Tree.create ~children node in let build_root visited package = build visited package (Root package) in root |> OpamPackage.Set.elements |> List.fold_left_map build_root OpamPackage.Set.empty |> snd let build_revdeps_forest st universe tog filter names = let { OpamListCommand.build; post; _ } = tog in let root, graph = let graph = OpamSolver.dependency_graph ~depopts:false ~build ~post ~installed:true ~unavailable:false universe in let root = st.installed |> OpamPackage.Set.filter (is_leaf graph) in match OpamPackage.Set.is_empty names, filter with | false, Roots_from -> names, graph | false, Leads_to -> cut_leaves `succ ~names ~root st graph | true, _ -> root, graph in let condition_map = build_condition_map tog st in let rec build visited package node = if visited |> OpamPackage.Set.mem package then let node = match node with | Root p -> Root p (* but impossible *) | Requirement x -> Requirement { x with is_dup = true } in visited, Tree.create node else let visited = visited |> OpamPackage.Set.add package in let pred = OpamSolver.PkgGraph.pred graph package in let visited, children = List.fold_left_map (fun visited child -> let demands = condition_map |> OpamPackage.Map.find child |> OpamPackage.Name.Map.find_opt package.name in let child_node = Requirement { package = child; demands; is_dup = false } in build visited child child_node ) visited pred in visited, Tree.create ~children node in let build_root visited package = let visited = OpamPackage.Set.(remove package (union visited root)) in build visited package (Root package) in root |> OpamPackage.Set.elements |> List.fold_left_map build_root OpamPackage.Set.empty |> snd let build st universe tog mode filter names = match mode with | Deps -> DepsForest (build_deps_forest st universe tog filter names) | ReverseDeps -> RevdepsForest (build_revdeps_forest st universe tog filter names) (* Forest printing *) let string_of_condition cond = let custom ~context:_ ~paren:_ = function | FString s -> Some s | _ -> None in let string_of_atom fc = match fc with | Filter f -> OpamFilter.to_string ~custom f | Constraint (relop, f) -> Printf.sprintf "%s %s" (OpamPrinter.FullPos.relop_kind relop) (OpamFilter.to_string ~custom f) in "(" ^ OpamFormula.string_of_formula string_of_atom cond ^ ")" let duplicate_symbol = "[*]" let print_deps ?(no_constraint=false) = function | Root p -> OpamPackage.to_string p | Dependency { package; satisfies; is_dup } -> let p = OpamPackage.to_string package in let dup = if is_dup then " "^duplicate_symbol else "" in match satisfies with | _ when no_constraint -> Printf.sprintf "%s%s" p dup | None | Some Empty -> Printf.sprintf "%s%s" p dup | Some c -> Printf.sprintf "%s %s%s" p (string_of_condition c) dup let print_revdeps ?(no_constraint=false) = function | Root p -> OpamPackage.to_string p | Requirement { package; demands; is_dup } -> let p = OpamPackage.to_string package in let dup = if is_dup then " "^duplicate_symbol else "" in match demands with | _ when no_constraint -> Printf.sprintf "%s%s" p dup | None | Some Empty -> Printf.sprintf "%s%s" p dup | Some c -> Printf.sprintf "%s %s%s" (string_of_condition c) p dup let print ?no_constraint = function | DepsForest (tree :: trees) -> let printer = print_deps ?no_constraint in Tree.print ~printer tree; trees |> List.iter (fun tree -> print_newline (); Tree.print ~printer tree) | RevdepsForest (tree :: trees) -> let printer = print_revdeps ?no_constraint in Tree.print ~printer tree; trees |> List.iter (fun tree -> print_newline (); Tree.print ~printer tree) | DepsForest [] | RevdepsForest [] -> () let name_version_json nv = [ "name", OpamPackage.Name.to_json (OpamPackage.name nv); "version", OpamPackage.Version.to_json (OpamPackage.version nv) ] let deps_to_json_fields ?(no_constraint=false) = function | Root p -> name_version_json p | Dependency { package; satisfies; is_dup } -> let p = name_version_json package in let s = if no_constraint then [] else match satisfies with | None | Some Empty -> ["satisfies", `Null] | Some c -> ["satisfies", `String (string_of_condition c)] in let d = ["is_duplicate", `Bool is_dup] in p @ s @ d let revdeps_to_json_fields ?(no_constraint=false) = function | Root p -> name_version_json p | Requirement { package; demands; is_dup } -> let p = name_version_json package in let s = if no_constraint then [] else match demands with | None | Some Empty -> ["demands", `Null] | Some c -> ["demands", `String (string_of_condition c)] in let d = ["is_duplicate", `Bool is_dup] in p @ s @ d let rec tree_to_json children value_to_fields t = let cs = List.map (tree_to_json children value_to_fields) (Tree.children t) in `O (value_to_fields (Tree.value t) @ [children, `A cs]) let forest_to_json ?no_constraint forest = match forest with | DepsForest xs -> `A (List.map (tree_to_json "dependencies" (deps_to_json_fields ?no_constraint)) xs) | RevdepsForest xs -> `A (List.map (tree_to_json "requirements" (revdeps_to_json_fields ?no_constraint)) xs) let print_solution st new_st missing solution = OpamConsole.msg "The following actions are simulated:\n"; let messages p = let opam = OpamSwitchState.opam new_st p in let messages = OpamFile.OPAM.messages opam in List.filter_map (fun (s,f) -> if OpamFilter.opt_eval_to_bool (OpamPackageVar.resolve ~opam new_st) f then Some s else None ) messages in let append nv = let pinned = if OpamPackage.Set.mem nv st.pinned then " (pinned)" else "" and deprecated = let opam = OpamSwitchState.opam new_st nv in if OpamFile.OPAM.has_flag Pkgflag_Deprecated opam then " (deprecated)" else "" in pinned ^ deprecated in let skip = OpamPackage.Set.fold (fun p m -> OpamPackage.Map.add p p m) (Lazy.force new_st.reinstall) OpamPackage.Map.empty in OpamSolver.print_solution ~messages ~append ~requested:missing ~reinstall:(Lazy.force st.reinstall) ~available:(Lazy.force st.available_packages) ~skip (* hide recompiled packages because they don't make sense here *) Install solution; OpamConsole.msg "\n" (** Setting states for building *) let get_universe tog requested st = let { OpamListCommand.doc; test; dev_setup; dev; _} = tog in OpamSwitchState.universe st ~doc ~test ~dev_setup ~force_dev_deps:dev ~requested Query let dry_install tog st universe install = match OpamSolver.resolve universe (OpamSolver.request ~install ()) with | Success solution -> let new_st = OpamSolution.dry_run st solution in print_solution st new_st (OpamPackage.Name.Set.of_list (List.map fst install)) solution; let requested = OpamFormula.packages_of_atoms new_st.installed install in new_st, get_universe tog requested new_st | Conflicts cs -> OpamConsole.error "Could not simulate installing the specified package(s) to this switch:"; OpamConsole.errmsg "%s" (OpamCudf.string_of_conflicts st.packages (OpamSwitchState.unavailable_reason st) cs); OpamStd.Sys.exit_because `No_solution let run st tog ?no_constraint mode filter atoms = let open OpamPackage.Set.Op in let select, missing = List.fold_left (fun (select, missing) atom -> let installed = OpamPackage.Set.filter (OpamFormula.check atom) st.installed in if OpamPackage.Set.is_empty installed then (select, atom :: missing) else (installed ++ select, missing)) (OpamPackage.Set.empty, []) atoms in let st, universe = let universe = let requested = OpamFormula.packages_of_atoms (if missing = [] then st.installed else st.packages) atoms in get_universe tog requested st in match mode, filter, missing with | Deps, _, [] -> st, universe | Deps, Roots_from, _::_ -> dry_install tog st universe missing | Deps, Leads_to, _::_ | ReverseDeps, _, _ -> (* non-installed names don't make sense in rev-deps *) if missing <> [] then OpamConsole.warning "Not installed package%s %s, skipping" (match missing with | [_] -> "" | _ -> "s") (OpamStd.Format.pretty_list (List.map OpamFormula.string_of_atom missing)); if OpamPackage.Set.is_empty select && atoms <> [] then OpamConsole.error_and_exit `Not_found "No package to display" else st, universe in if OpamPackage.Set.is_empty st.installed then OpamConsole.error_and_exit `Not_found "No package is installed" else let simulated = OpamFormula.packages_of_atoms st.installed missing in let forest = build st universe tog mode filter (select ++ simulated) in print ?no_constraint forest; if OpamClientConfig.(!r.json_out) <> None then (if OpamSwitch.compare st.switch OpamSwitch.unset <> 0 then OpamJson.append "switch" (OpamSwitch.to_json st.switch); OpamJson.append "tree" (forest_to_json ?no_constraint forest))
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>