From a427b81382dedadb2c596212fc62021d62f37056 Mon Sep 17 00:00:00 2001 From: Louis Gesbert Date: Thu, 26 Jun 2014 14:53:48 +0200 Subject: [PATCH] Add 'opam show --depends --external ' --- CHANGES | 5 ++-- src/client/opamArg.ml | 34 +++++++++++++++++++----- src/client/opamClient.ml | 54 +++++++++++++++++++++++++++++++++++++-- src/client/opamClient.mli | 5 +++- 4 files changed, 87 insertions(+), 11 deletions(-) diff --git a/CHANGES b/CHANGES index 8a1eb081fa4..1893166312b 100644 --- a/CHANGES +++ b/CHANGES @@ -40,8 +40,7 @@ 0.9.4, cudf 0.7 * Switch export file now include pinning data. Pinned package restored through 'opam switch import' (#1393) -* Meaningful messages explaining conflicts and why packages aren't available - (#1238, #1419, #1398) +* Meaningful messages explaining why packages aren't available (#1419, #1398) * More informative 'opam config list', more complete 'opam config var' * Added 'opam config cudf-universe' for use in external tools * opam files: added a 'dev-repo' field, and the experimental 'flags' field @@ -51,6 +50,8 @@ * Added 'opam upgrade --fixup' to save the day if your installed package set gets inconsistent. * Fixed some return codes +* Added options '--raw', '--depends', '--external' and more fields to 'opam + show' * Hundreds of smaller fixes and UI improvements 1.1.2 diff --git a/src/client/opamArg.ml b/src/client/opamArg.ml index b6a8cca965f..abf3d87421f 100644 --- a/src/client/opamArg.ml +++ b/src/client/opamArg.ml @@ -489,6 +489,12 @@ let atom_list = e.g `pkg', `pkg.1.0' or `pkg>=0.5'." atom +let nonempty_atom_list = + nonempty_arg_list "PACKAGES" + "List of package names, with an optional version or constraint, \ + e.g `pkg', `pkg.1.0' or `pkg>=0.5'." + atom + let param_list = arg_list "PARAMS" "List of parameters." Arg.string @@ -788,11 +794,27 @@ let show = Arg.(value & opt (list string) [] & doc) in let raw = mk_flag ["raw"] "Print the raw opam file for this package" in - - let pkg_info global_options fields raw packages = + let depends = + mk_flag ["d";"depends"] "Print the list of packages these ones \ + transitively depend on (latest versions only)" in + let depexts = + mk_opt ["e";"external"] "TAGS" + "Display the external package dependencies associated to the given \ + $(i,TAGS) (OS, distribution...). With `--depends', display them for \ + the set of dependencies." + Arg.(list string) [] in + let pkg_info global_options fields raw depends depexts packages = apply_global_options global_options; - Client.info ~fields ~raw_opam:raw packages in - Term.(pure pkg_info $global_options $fields $raw $nonempty_pattern_list), + if depends || depexts <> [] then + if raw || fields <> [] then + `Error (true, "Incompatible options specified") + else + `Ok (Client.depends ~depends ~depexts packages) + else + `Ok (Client.info ~fields ~raw_opam:raw packages) in + Term.ret + Term.(pure pkg_info $global_options $fields $raw $depends $depexts + $nonempty_atom_list), term_info "show" ~doc ~man @@ -1071,7 +1093,7 @@ let install = Client.install atoms add_to_roots deps_only in Term.(pure install $global_options $build_options - $add_to_roots $deps_only $atom_list), + $add_to_roots $deps_only $nonempty_atom_list), term_info "install" ~doc ~man (* REMOVE *) @@ -1115,7 +1137,7 @@ let reinstall = apply_global_options global_options; apply_build_options build_options; Client.reinstall atoms in - Term.(pure reinstall $global_options $build_options $atom_list), + Term.(pure reinstall $global_options $build_options $nonempty_atom_list), term_info "reinstall" ~doc ~man (* UPDATE *) diff --git a/src/client/opamClient.ml b/src/client/opamClient.ml index dd539c91ea7..066bcdf62ff 100644 --- a/src/client/opamClient.ml +++ b/src/client/opamClient.ml @@ -245,11 +245,12 @@ module API = struct ) names; if names = [] then OpamGlobals.exit 1 - let info ~fields ~raw_opam regexps = + let info ~fields ~raw_opam atoms = let t = OpamState.load_state "info" in let names = names_of_regexp t ~filter:`all ~depends_on:[] - ~exact_name:true ~case_sensitive:false regexps in + ~exact_name:true ~case_sensitive:false + (List.map OpamFormula.short_string_of_atom atoms) in let show_fields = List.length fields <> 1 in @@ -1042,6 +1043,52 @@ module API = struct let t = update_dev_packages_t atoms t in install_t atoms add_to_roots deps_only t + let depends ?(depends=true) ?depexts atoms = + let t = OpamState.load_state "client-depends" in + let atoms = OpamSolution.sanitize_atom_list ~permissive:true t atoms in + let latest_versions_only packages = + OpamPackage.Set.map (fun nv -> + OpamPackage.max_version packages (OpamPackage.name nv)) + packages + in + let packages = latest_versions_only (packages_of_atoms t atoms) in + let packages = + if depends then + let universe = OpamState.universe t Depends in + OpamSolver.dependencies + ~depopts:false ~installed:false universe packages + |> OpamPackage.Set.of_list + |> latest_versions_only + else packages + in + let packages = latest_versions_only packages in + match depexts with + | None | Some [] -> + OpamGlobals.msg "%s\n" @@ + String.concat " " @@ + List.map OpamPackage.to_string @@ + OpamPackage.Set.elements packages + | Some required_tags -> + let required_tags = OpamMisc.StringSet.of_list required_tags in + let depexts = + OpamPackage.Set.fold (fun nv acc -> + let opam = OpamState.opam t nv in + match OpamFile.OPAM.depexts opam with + | None -> acc + | Some tags -> + OpamMisc.StringSetMap.fold (fun tags values acc -> + if OpamMisc.StringSet.for_all + (fun tag -> OpamMisc.StringSet.mem tag required_tags) + tags + then OpamMisc.StringSet.union acc values + else acc) + tags acc) + packages OpamMisc.StringSet.empty + in + OpamGlobals.msg "%s\n" @@ + String.concat " " @@ + OpamMisc.StringSet.elements depexts + let remove_t ?ask ~autoremove ~force atoms t = log "REMOVE autoremove:%b %a" autoremove (slog OpamFormula.string_of_atoms) atoms; @@ -1307,6 +1354,9 @@ module SafeAPI = struct let info ~fields ~raw_opam regexps = read_lock (fun () -> API.info ~fields ~raw_opam regexps) + let depends ?depends ?depexts names = + read_lock (fun () -> API.depends ?depends ?depexts names) + let install names add_to_roots deps_only = switch_lock (fun () -> API.install names add_to_roots deps_only) diff --git a/src/client/opamClient.mli b/src/client/opamClient.mli index 6e612e1f49d..88299accfb7 100644 --- a/src/client/opamClient.mli +++ b/src/client/opamClient.mli @@ -40,7 +40,10 @@ module API: sig unit (** Display a general summary of a collection of packages. *) - val info: fields:string list -> raw_opam:bool -> string list -> unit + val info: fields:string list -> raw_opam:bool -> atom list -> unit + + (** Display dependencies or external dependencies of packages. *) + val depends: ?depends:bool -> ?depexts:string list -> atom list -> unit (** Install the given list of packages. Second argument, if not None, specifies that given packages should be added or removed from the roots.