From 102562e3a20942e6c7ffb5869bf9abeb0fd2d4b7 Mon Sep 17 00:00:00 2001 From: Michele Alberti <michele.alberti@cea.fr> Date: Tue, 9 Mar 2021 16:43:10 +0100 Subject: [PATCH] Improve detect option of config command. - DIR must be set with absolute paths, otherwise an error is displayed. - Create, write and close the configuration file only if no failure happens during the detection process (note that empty detection is fine). --- main.ml | 13 +++++++------ solver.ml | 42 ++++++++++++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/main.ml b/main.ml index c4f1cb2..5a7b015 100644 --- a/main.ml +++ b/main.ml @@ -45,8 +45,7 @@ let setup_logs = (* Commands. *) -let config cmd detect file_opt () = - let file = Option.value file_opt ~default:Solver.default_config_file in +let config cmd detect file () = Logs.debug (fun m -> m "Command `%s' with configuration file `%s'." cmd file); if detect @@ -81,7 +80,8 @@ let config_cmd = let dirvar = "DIR" in let envs = [ Term.env_info - ~doc:"Path to directory where to search for the executable of a solver." + ~doc:"Absolute path to the directory containing the executable \ + of a solver." dirvar ] in let detect = @@ -95,7 +95,7 @@ let config_cmd = let doc = Format.sprintf "$(b,FILE) to write the %s configuration to." caisar in - Arg.(value & pos 0 (some string) None + Arg.(value & pos 0 string Solver.default_config_file & info [] ~docv:docv_filename ~doc) in let doc = Format.sprintf "%s configuration." caisar in @@ -106,10 +106,11 @@ let config_cmd = in Term.(ret (const (fun cmdname detect filename _ -> - if not detect && Option.is_none filename + if not detect then `Help (`Pager, Some "config") else - (* TODO: Do not enable [detect] by default. *) + (* TODO: Do not only check for [detect], and enable it by + default, as soon as other options are available. *) `Ok (config cmdname true filename ())) $ const cmdname $ detect $ filename $ setup_logs)), Term.info cmdname ~sdocs:Manpage.s_common_options ~envs ~exits ~doc ~man diff --git a/solver.ml b/solver.ml index d23c0ea..da23db8 100644 --- a/solver.ml +++ b/solver.ml @@ -7,6 +7,7 @@ open Base module Format = Caml.Format module Sys = Caml.Sys +module Filename = Caml.Filename (* Supported solvers. *) type solver = @@ -66,7 +67,6 @@ let exe_path_of_solver solver = begin (* We want the complete path of [exe] in $PATH: we use `command -v [exe]' and retrieve the result, if any. *) - let module Filename = Caml.Filename in let tmp = Filename.temp_file "caisar" "command" in let _retcode = Sys.command @@ -78,12 +78,24 @@ let exe_path_of_solver solver = let exe = try Stdlib.input_line in_channel with End_of_file -> exe in Stdlib.close_in in_channel; Sys.remove tmp; - exe + Ok exe end - | Some v -> + | Some dir -> (* The env variable should already provide the path to the executable: we - just concatenate to it the [exe] name. *) - v ^ exe + first check that the path is absolute, and then concatenate the [exe] + name to it. *) + if Filename.is_relative dir + then + Error + "Variable DIR is set with a relative path. \ + An absolute path is required." + else + let exe = + if Filename.check_suffix dir Filename.dir_sep + then dir ^ exe + else Format.sprintf "%s%s%s" dir Filename.dir_sep exe + in + Ok exe (* Configuration. *) @@ -169,7 +181,6 @@ let create_config_file file = Stdlib.open_out file let detect_default_solvers () = - let module Filename = Caml.Filename in try let config = List.filter_map @@ -178,7 +189,11 @@ let detect_default_solvers () = provided path via env variable, by executing `solver --version' command. *) let tmp = Filename.temp_file "caisar" "detect" in - let exe = exe_path_of_solver solver in + let exe = + (* Failwith upon error case in [exe_path_of_solver] just to + propogate the error message to the user. *) + Result.ok_or_failwith (exe_path_of_solver solver) + in let cmd = Filename.quote_command ~stdout:tmp ~stderr:tmp @@ -212,17 +227,21 @@ let detect_default_solvers () = defaults in Ok config - with _ -> + with + | Failure msg -> + (* Must be only due to the previous use of the [ok_or_failwith]. *) + Error msg + | _ -> Error "Unexpected failure." let detect ~file = let open Result in + (* Detect default supported solvers in $PATH or $DIR. *) + detect_default_solvers () >>= fun default_full_config -> (* Retrieve the current configuration from [file]. *) let current_full_config = get_full_config file in (* Create new configuration file. *) let out_channel = create_config_file file in - (* Detect default supported solvers in $PATH or $DIR. *) - detect_default_solvers () >>= fun default_full_config -> (* Build [full_config] by first appending [default_full_config] to [current_full_config], and then deduping the result. *) let full_config = @@ -236,13 +255,13 @@ let detect ~file = (* We write all solver configs in the configuration file, as JSON data. *) let full_config_json = full_config_to_yojson full_config in Yojson.Safe.pretty_to_channel out_channel full_config_json; + Stdlib.close_out out_channel; Ok () (* Verification. *) let check_availability config = - let module Filename = Caml.Filename in Logs.debug (fun m -> m "Checking actual availability of `%a'." pp_solver config.solver); @@ -287,7 +306,6 @@ let check_compatibility config model = Ok () let build_command ~raw_options confg_solver property model = - let module Filename = Caml.Filename in let open Result in let solver = confg_solver.solver in (* Format property wrt solver. *) -- GitLab