diff --git a/doc/dev-manual/dev-manual.pdf b/doc/dev-manual/dev-manual.pdf index 12fc7e2e638..c0cd45b3f6f 100644 Binary files a/doc/dev-manual/dev-manual.pdf and b/doc/dev-manual/dev-manual.pdf differ diff --git a/doc/dev-manual/dev-manual.tex b/doc/dev-manual/dev-manual.tex index a03deb54817..e626e207e00 100644 --- a/doc/dev-manual/dev-manual.tex +++ b/doc/dev-manual/dev-manual.tex @@ -210,17 +210,43 @@ \subsubsection{Global Configuration File: {\tt config}} opam-version: "1.2" repositories: [ STRING+ ] switch: STRING - cores: INT + ?jobs: INT + ?solver: + ?solver-criteria: STRING + ?solver-upgrade-criteria: STRING + ?solver-fixup-criteria: STRING + ?download-command: + ?download-jobs: INT + + := [ ( ?{ })+ ] \end{Verbatim} -The field {\tt opam-version} indicates the current \OPAM\ format. - -The field {\tt repositories} contains the list of \OPAM\ repositories. - -The field {\tt switch} corresponds to the current compiler instance. - -The field {\tt cores} is the number of parallel process that -\OPAM\ will use when trying to build the packages. +\begin{itemize} +\item {\tt opam-version} indicates the current \OPAM\ repository format -- + normally corresponding to the \OPAM\ minor version (\verb+MAJOR.MINOR+) +\item {\tt repositories} contains the names of the currently configured + repositories. +\item {\tt switch} is the name of the currently active \OPAM\ switch. +\item {\tt jobs} is the maximum number of build processes that can be run + simultaneously. +\item {\tt solver} is the external solver to call. The value may be either the + single identifiers \verb+aspcud+ or \verb+packup+, which have built-in + support, or a command. The string variables \verb+input+, \verb+output+ and + \verb+criteria+ (only) are defined when evaluating this field. +\item {\tt solver-criteria}, {\tt solver-upgrade-criteria} and {\tt + solver-fixup-criteria} are the optimisation criteria provided to the solver + resp. in the default case (install requested packages at their latest version, + minimising the impact on other packages), for global upgrades (minimise + outdated packages) and for fixup (resolve dependencies while minimising + changes). +\item {\tt download-command} will be called to fetch remote files over http(s) + or ftp. The value may be either the single identifiers \verb+curl+ or + \verb+wget+, which have built-in support, or a custom command. Only the + special variables \verb+url+, \verb+out+, \verb+retries+ (strings) and + \verb+compress+ (bool) can be used in this field. +\item {\tt download-jobs} is the maximum number of simultaneous downloads (all + remote hosts included) +\end{itemize} \subsubsection{Package Specification files: {\tt opam}} \label{file:opam} diff --git a/src/client/opamArg.ml b/src/client/opamArg.ml index aebd4adfbd4..8363ea999ab 100644 --- a/src/client/opamArg.ml +++ b/src/client/opamArg.ml @@ -130,11 +130,11 @@ let apply_global_options o = OpamGlobals.yes := !OpamGlobals.yes || o.yes; OpamGlobals.strict := !OpamGlobals.strict || o.strict; OpamGlobals.no_base_packages := !OpamGlobals.no_base_packages || o.no_base_packages; - OpamGlobals.external_solver := - OpamMisc.Option.Op.(o.external_solver ++ !OpamGlobals.external_solver); + OpamGlobals.env_external_solver := + OpamMisc.Option.Op.(o.external_solver ++ !OpamGlobals.env_external_solver); OpamGlobals.use_external_solver := !OpamGlobals.use_external_solver && not o.use_internal_solver && - !OpamGlobals.external_solver <> Some ""; + !OpamGlobals.env_external_solver <> Some ""; OpamGlobals.cudf_file := OpamMisc.Option.Op.(o.cudf_file ++ !OpamGlobals.cudf_file); OpamGlobals.no_self_upgrade := !OpamGlobals.no_self_upgrade || o.no_self_upgrade; @@ -215,11 +215,15 @@ let help_sections = [ `P ("$(i,OPAMCRITERIA) specifies user $(i,preferences) for dependency solving.\ The default value is "^OpamGlobals.default_preferences `Default^". \ See also option --criteria"); - `P "$(i,OPAMCURL) can be used to define an alternative for the 'curl' \ - command-line utility to download files."; + `P "$(i,OPAMCURL) can be used to select a given 'curl' program. See \ + $(i,OPAMFETCH) for more options."; `P "$(i,OPAMDEBUG) see options `--debug' and `--debug-level'."; `P "$(i,OPAMDOWNLOADJOBS) sets the maximum number of simultaneous downloads."; `P "$(i,OPAMEXTERNALSOLVER) see option `--solver'."; + `P "$(i,OPAMFETCH) specifies how to download files: either `wget', `curl' or \ + a custom command where variables $(b,%{url}%), $(b,%{out}%), \ + $(b,%{retries}%) and $(b,%{compress}%) will be replaced. Overrides the \ + 'download-command' value from the main config file."; `P "$(i,OPAMJOBS) sets the maximum number of parallel workers to run."; `P "$(i,OPAMLOCKRETRIES) sets the number of tries after which OPAM gives up \ acquiring its lock and fails. <= 0 means infinite wait."; @@ -597,7 +601,9 @@ let global_options = let external_solver = mk_opt ~section ["solver"] "CMD" ("Specify the name of the external dependency $(i,solver). \ - The default value is "^OpamGlobals.default_external_solver) + The default value is "^OpamGlobals.default_external_solver^ + ". Either 'aspcud', 'packup' or a custom command that may contain \ + the variables %{input}%, %{output}% and %{criteria}%") Arg.(some string) None in let solver_preferences = mk_opt ~section ["criteria"] "CRITERIA" @@ -1051,7 +1057,9 @@ let config = print "os" "%s" (OpamGlobals.os_string ()); print "external-solver" "%s" (if OpamCudf.external_solver_available () then - OpamGlobals.get_external_solver () + String.concat " " + (OpamGlobals.external_solver + ~input:"$in" ~output:"$out" ~criteria:"$criteria") else "no"); print "criteria" "%s" (try List.assoc `Default !OpamGlobals.solver_preferences diff --git a/src/client/opamClient.ml b/src/client/opamClient.ml index d471a0b2936..547baa554e6 100644 --- a/src/client/opamClient.ml +++ b/src/client/opamClient.ml @@ -1224,10 +1224,10 @@ module API = struct install the %s command on your system." msg (OpamGlobals.colorise `bold cmd)) unavailable_repos); - if not (check_external_dep (OpamGlobals.get_external_solver())) then + if not (check_external_dep (OpamGlobals.default_external_solver)) then OpamGlobals.warning "Recommended external solver %s not found." - (OpamGlobals.colorise `bold (OpamGlobals.get_external_solver ())); + (OpamGlobals.colorise `bold (OpamGlobals.default_external_solver)); let advised_deps = [!OpamGlobals.makecmd(); "m4"; "cc"] in (match List.filter (not @* check_external_dep) advised_deps with | [] -> () @@ -1238,9 +1238,14 @@ module API = struct (OpamMisc.itemize (OpamGlobals.colorise `bold) missing)); let required_deps = ["curl or wget", - check_external_dep - (OpamMisc.Option.default "curl" OpamGlobals.curl_command) - || check_external_dep "wget"; + check_external_dep OpamGlobals.curl_command || + check_external_dep "wget" || + (match !OpamGlobals.download_tool with + | Some (`Custom f) -> + (match f ~url:"" ~out:"-" ~retry:1 ~compress:false with + | cmd::_ -> check_external_dep cmd + | [] -> false) + | _ -> false); "patch", check_external_dep "patch"; "tar", check_external_dep "tar"; "unzip", check_external_dep "unzip" ] diff --git a/src/client/opamState.ml b/src/client/opamState.ml index 0df11e134b5..37af03c3934 100644 --- a/src/client/opamState.ml +++ b/src/client/opamState.ml @@ -1383,13 +1383,9 @@ let upgrade_to_1_1_hook = let upgrade_to_1_2_hook = ref (fun () -> assert false) -let load_state ?(save_cache=true) call_site = - log "LOAD-STATE(%s)" call_site; - let chrono = OpamGlobals.timer () in - !upgrade_to_1_1_hook (); - - let root = OpamPath.root () in - +(* Loads the global config file and update some global references in + OpamGlobals *) +let load_config root = let config_p = OpamPath.config root in let config = let config = OpamFile.Config.read config_p in @@ -1411,10 +1407,46 @@ let load_state ?(save_cache=true) call_site = ) else config in - OpamGlobals.external_solver := - OpamMisc.Option.Op.( - !OpamGlobals.external_solver ++ - OpamFile.Config.solver config); + let command_of_string s = + List.map (fun s -> CString s, None) (OpamMisc.split s ' ') + in + (* Set some globals *) + let external_solver_command = + let cmd = match !OpamGlobals.env_external_solver with + | Some ("aspcud" | "packup" as s) -> [CIdent s, None] + | Some s -> command_of_string s + | None -> match OpamFile.Config.solver config with + | Some f -> + OpamGlobals.env_external_solver := + Some (OpamMisc.sconcat_map " " + (function (CIdent i,_) -> "%{"^i^"}%" | (CString s,_) -> s) + f); + f + | None -> [CIdent OpamGlobals.default_external_solver, None] + in + let cmd = match cmd with + | [CIdent "aspcud", None] -> + List.map (fun s -> s, None) + [CString "aspcud"; CIdent "input"; CIdent "output"; CIdent "criteria"] + | [CIdent "packup", None] -> + List.map (fun s -> s, None) + [CString "packup"; CIdent "input"; CIdent "output"; + CString "-u"; CIdent "criteria"] + | cmd -> cmd + in + fun ~input ~output ~criteria -> + OpamFilter.single_command (fun v -> + if not (is_global_conf v) then None else + match OpamVariable.to_string (OpamVariable.Full.variable v) with + | "input" -> Some (S input) + | "output" -> Some (S output) + | "criteria" -> Some (S criteria) + | _ -> None) + cmd + in + + OpamGlobals.external_solver_ref := Some external_solver_command; + let solver_prefs = let config_crit = !OpamGlobals.solver_preferences @ OpamFile.Config.criteria config in @@ -1429,6 +1461,43 @@ let load_state ?(save_cache=true) call_site = in OpamGlobals.solver_preferences := solver_prefs; + let dl_tool = + match !OpamGlobals.download_tool_env with + | Some ("curl" | "wget" as s) -> Some [CIdent s, None] + | Some s -> Some (command_of_string s) + | None -> OpamFile.Config.dl_tool config + in + let dl_command cmd = + fun ~url ~out ~retry ~compress -> + OpamFilter.single_command (fun v -> + if not (is_global_conf v) then None else + match OpamVariable.to_string (OpamVariable.Full.variable v) with + | "url" -> Some (S url) + | "out" -> Some (S out) + | "retry" -> Some (S (string_of_int retry)) + | "compress" -> Some (B compress) + | _ -> None) + cmd + in + let download_tool = match dl_tool with + | Some [CIdent "curl", None] -> Some `Curl + | Some [CIdent "wget", None] -> Some `Wget + | Some cmd -> Some (`Custom (dl_command cmd)) + | None -> None + in + OpamGlobals.download_tool := download_tool; + + config + +let load_state ?(save_cache=true) call_site = + log "LOAD-STATE(%s)" call_site; + let chrono = OpamGlobals.timer () in + !upgrade_to_1_1_hook (); + + let root = OpamPath.root () in + + let config = load_config root in + let opams = let file = OpamPath.state_cache root in if OpamFilename.exists file then marshal_from_file file @@ -1470,7 +1539,7 @@ let load_state ?(save_cache=true) call_site = (OpamSwitch.to_string switch) (OpamSwitch.to_string new_switch); let config = OpamFile.Config.with_switch config new_switch in - OpamFile.Config.write config_p config; + OpamFile.Config.write (OpamPath.config root) config; new_switch, new_compiler; ) else OpamGlobals.error_and_exit diff --git a/src/core/opamFile.ml b/src/core/opamFile.ml index b1d599651e1..68df90ddb28 100644 --- a/src/core/opamFile.ml +++ b/src/core/opamFile.ml @@ -730,9 +730,10 @@ module X = struct repositories : repository_name list ; switch : switch; jobs : int; + dl_tool : arg list option; dl_jobs : int; criteria : (solver_criteria * string) list; - solver : string option; + solver : arg list option; } let with_repositories t repositories = { t with repositories } @@ -745,13 +746,14 @@ module X = struct let repositories t = t.repositories let switch t = t.switch let jobs t = t.jobs + let dl_tool t = t.dl_tool let dl_jobs t = t.dl_jobs let criteria t = t.criteria let solver t = t.solver - let create switch repositories ?(criteria=[]) ?solver jobs dl_jobs = + let create switch repositories ?(criteria=[]) ?solver jobs ?download_tool dl_jobs = { opam_version = OpamVersion.current; - repositories ; switch ; jobs ; dl_jobs ; + repositories ; switch ; jobs ; dl_tool = download_tool; dl_jobs ; criteria ; solver } let empty = { @@ -759,6 +761,7 @@ module X = struct repositories = []; switch = OpamSwitch.of_string ""; jobs = OpamGlobals.default_jobs; + dl_tool = None; dl_jobs = OpamGlobals.default_dl_jobs; criteria = []; solver = None; @@ -771,6 +774,7 @@ module X = struct let s_switch2 = "ocaml-version" let s_jobs = "jobs" + let s_dl_tool = "download-command" let s_dl_jobs = "download-jobs" let s_criteria = "solver-criteria" let s_upgrade_criteria = "solver-upgrade-criteria" @@ -787,6 +791,7 @@ module X = struct s_repositories; s_switch; s_jobs; + s_dl_tool; s_dl_jobs; s_criteria; s_upgrade_criteria; @@ -821,23 +826,29 @@ module X = struct let switch1 = mk_switch s_switch1 in let switch2 = mk_switch s_switch2 in let switch = - match switch, switch1, switch2 with - | Some v, _ , _ - | _ , Some v, _ - | _ , _ , Some v -> v - | None , None , None -> OpamGlobals.error_and_exit - "No current switch defined." in + match OpamMisc.Option.Op.(switch ++ switch1 ++ switch2) with + | Some v -> v + | None -> OpamGlobals.error_and_exit + "No current switch defined in %s." + (OpamFilename.to_string filename) in let jobs = try - let mk str = OpamFormat.assoc_option s.file_contents str OpamFormat.parse_int in - match mk s_jobs, mk s_cores with - | Some i, _ -> i - | _ , Some i -> i - | _ -> 1 + let mk str = + OpamFormat.assoc_option s.file_contents str OpamFormat.parse_int in + match OpamMisc.Option.Op.(mk s_jobs ++ mk s_cores) with + | Some i -> i + | None -> OpamGlobals.default_jobs with OpamFormat.Bad_format _ when permissive -> OpamGlobals.default_jobs in + let dl_tool = + try + OpamFormat.assoc_option s.file_contents s_dl_tool + OpamFormat.parse_single_command + with OpamFormat.Bad_format _ when permissive -> None + in + let dl_jobs = try match OpamFormat.assoc_option s.file_contents s_dl_jobs @@ -862,9 +873,12 @@ module X = struct in let solver = - OpamFormat.assoc_option s.file_contents s_solver OpamFormat.parse_string + try + OpamFormat.assoc_option s.file_contents s_solver + OpamFormat.parse_single_command + with OpamFormat.Bad_format _ when permissive -> None in - { opam_version; repositories; switch; jobs; dl_jobs; + { opam_version; repositories; switch; jobs; dl_tool; dl_jobs; criteria; solver } let to_string filename t = @@ -882,7 +896,14 @@ module X = struct let solver = match t.solver with | None -> [] | Some s -> - [OpamFormat.make_variable (s_solver, OpamFormat.make_string s)] + [OpamFormat.make_variable + (s_solver, OpamFormat.make_single_command s)] + in + let download_tool = match t.dl_tool with + | None -> [] + | Some dlt -> + [OpamFormat.make_variable + (s_dl_tool, OpamFormat.make_single_command dlt)] in let s = { file_format = OpamVersion.current; @@ -899,6 +920,7 @@ module X = struct OpamFormat.make_variable (s_switch, OpamFormat.make_string (OpamSwitch.to_string t.switch)) ] @ criteria @ solver + @ download_tool } in Syntax.to_string s end diff --git a/src/core/opamFile.mli b/src/core/opamFile.mli index d228be0be7b..2a82f40767c 100644 --- a/src/core/opamFile.mli +++ b/src/core/opamFile.mli @@ -57,8 +57,9 @@ module Config: sig switch -> repository_name list -> ?criteria:(OpamTypes.solver_criteria * string) list -> - ?solver:string -> + ?solver:(arg list) -> int -> + ?download_tool:(arg list) -> int -> t @@ -73,7 +74,7 @@ module Config: sig val with_criteria: t -> (solver_criteria * string) list -> t - val with_solver: t -> string option -> t + val with_solver: t -> arg list option -> t (** Return the OPAM version *) val opam_version: t -> opam_version @@ -87,12 +88,14 @@ module Config: sig (** Return the number of jobs *) val jobs: t -> int + val dl_tool: t -> arg list option + (** Return the number of download jobs *) val dl_jobs: t -> int val criteria: t -> (solver_criteria * string) list - val solver: t -> string option + val solver: t -> arg list option end diff --git a/src/core/opamFilter.ml b/src/core/opamFilter.ml index a40cf094df2..5b07ba23987 100644 --- a/src/core/opamFilter.ml +++ b/src/core/opamFilter.ml @@ -253,3 +253,5 @@ let command env (l, f) = None let commands env l = OpamMisc.filter_map (command env) l + +let single_command env l = OpamMisc.filter_map (arguments env) l diff --git a/src/core/opamFilter.mli b/src/core/opamFilter.mli index b0f8822dcf0..b88cc01e73c 100644 --- a/src/core/opamFilter.mli +++ b/src/core/opamFilter.mli @@ -93,3 +93,6 @@ val expand_interpolations_in_file: env -> basename -> unit (** Processes filters evaluation in a command list: parameter expansion and conditional filtering *) val commands: env -> command list -> string list list + +(** Process a simpler command, without filters *) +val single_command: env -> arg list -> string list diff --git a/src/core/opamFormat.ml b/src/core/opamFormat.ml index 95dde77330b..f4766638daf 100644 --- a/src/core/opamFormat.ml +++ b/src/core/opamFormat.ml @@ -668,6 +668,8 @@ let make_simple_arg = function let make_arg = make_option make_simple_arg make_filter +let make_single_command = make_list make_arg + let make_command = make_option (make_list make_arg) make_filter @@ -689,6 +691,8 @@ let parse_simple_arg = let parse_arg = parse_option parse_simple_arg parse_filter +let parse_single_command = parse_list parse_arg + let parse_command = parse_option (parse_list parse_arg) parse_filter diff --git a/src/core/opamFormat.mli b/src/core/opamFormat.mli index 2371e5fec23..5a4370c01a2 100644 --- a/src/core/opamFormat.mli +++ b/src/core/opamFormat.mli @@ -238,6 +238,10 @@ val parse_filter: value list -> filter (** Creation *) val make_filter: filter -> value list +(** Unfiltered argument list *) +val parse_single_command: value -> arg list +val make_single_command: arg list -> value + (** Parse a command *) val parse_command: value -> command diff --git a/src/core/opamGlobals.ml b/src/core/opamGlobals.ml index 4528d2b464c..2300d0377a1 100644 --- a/src/core/opamGlobals.ml +++ b/src/core/opamGlobals.ml @@ -27,8 +27,11 @@ let check ?(warn=true) var = ref ( | "1" | "yes" | "true" -> true | v -> if warn then - Printf.eprintf "[WARNING] Invalid value %S for env variable OPAM%s, \ - assumed true.\n" v var; + prerr_endline + (OpamMisc.reformat ~indent:10 + (Printf.sprintf + "[WARNING] Invalid value %S for env variable OPAM%s, assumed \ + true." v var)); true with Not_found -> false ) @@ -101,8 +104,6 @@ let is_self_upgrade = try OpamMisc.getenv "OPAMNOSELFUPGRADE" = self_upgrade_bootstrapping_value with Not_found -> false -let curl_command = try Some (OpamMisc.getenv "OPAMCURL") with Not_found -> None - let jobs = ref ( try Some (int_of_string (OpamMisc.getenv "OPAMJOBS")) with Not_found | Failure _ -> None @@ -156,20 +157,37 @@ let get_solver_criteria action = let default_external_solver = "aspcud" -let external_solver = ref( - try Some (OpamMisc.strip (OpamMisc.getenv "OPAMEXTERNALSOLVER")) - with Not_found -> None) +let env_external_solver = + try ref (Some (OpamMisc.strip (OpamMisc.getenv "OPAMEXTERNALSOLVER"))) + with Not_found -> ref None + +let external_solver_ref = ref None let use_external_solver = ref (not (!(check "NOASPCUD") || !(check "USEINTERNALSOLVER") || - !external_solver = Some "")) + !env_external_solver = Some "")) -let get_external_solver () = - OpamMisc.Option.default default_external_solver !external_solver +let external_solver ~input ~output ~criteria = match !external_solver_ref with + | Some f -> f ~input ~output ~criteria + | None -> raise Not_found let default_repository_name = "default" let default_repository_address = "https://opam.ocaml.org" +let download_tool_env = + try ref (Some (OpamMisc.getenv "OPAMFETCH")) + with Not_found -> ref None + +let curl_command = try OpamMisc.getenv "OPAMCURL" with Not_found -> "curl" + +type download_tool = [ + | `Wget + | `Curl + | `Custom of + url:string -> out:string -> retry:int -> compress:bool -> string list +] +let download_tool = ref None + let search_files = ref ["findlib"] let default_build_command = [ [ "./build.sh" ] ] diff --git a/src/core/opamGlobals.mli b/src/core/opamGlobals.mli index 2391ee6e599..4ad0241d2fc 100644 --- a/src/core/opamGlobals.mli +++ b/src/core/opamGlobals.mli @@ -56,7 +56,6 @@ val all_parens : bool ref val self_upgrade_bootstrapping_value : string val is_self_upgrade : bool -val curl_command : string option val jobs : int option ref val dl_jobs : int option ref val download_retry : int @@ -73,9 +72,23 @@ val solver_preferences : (solver_criteria * string) list ref (** Get the currently configured solver criteria as a string *) val get_solver_criteria : [ `Default | `Upgrade | `Fixup ] -> string +val env_external_solver : string option ref val default_external_solver : string -val external_solver : string option ref -val get_external_solver : unit -> string + +val external_solver_ref : + (input:string -> output:string -> criteria:string -> string list) option ref +val external_solver : input:string -> output:string -> criteria:string -> string list + +type download_tool = [ + | `Wget + | `Curl + | `Custom of + url:string -> out:string -> retry:int -> compress:bool -> string list +] + +val download_tool_env: string option ref +val download_tool : download_tool option ref +val curl_command : string val default_repository_name : string val default_repository_address : string diff --git a/src/core/opamMisc.ml b/src/core/opamMisc.ml index 296b1a6c4d7..7c2e3aa591b 100644 --- a/src/core/opamMisc.ml +++ b/src/core/opamMisc.ml @@ -382,10 +382,10 @@ let contains s c = with Not_found -> false let split s c = - Re_str.split (Re_str.regexp (Printf.sprintf "[%c]" c)) s + Re_str.split (Re_str.regexp (Printf.sprintf "[%c]+" c)) s let split_delim s c = - Re_str.split_delim (Re_str.regexp (Printf.sprintf "[%c]" c)) s + Re_str.split_delim (Re_str.regexp (Printf.sprintf "[%c]+" c)) s let visual_length_substring s ofs len = let rec aux s i = diff --git a/src/core/opamSystem.ml b/src/core/opamSystem.ml index 96f58b7d0fb..c18826a69a4 100644 --- a/src/core/opamSystem.ml +++ b/src/core/opamSystem.ml @@ -672,6 +672,20 @@ let system_ocamlc_where = system [ "ocamlc"; "-where" ] let system_ocamlc_version = system [ "ocamlc"; "-version" ] +let choose_download_tool () = + match !OpamGlobals.download_tool with + | Some t -> t + | None -> + if OpamGlobals.os () = OpamGlobals.Darwin && command_exists "wget" + then `Wget + else if command_exists OpamGlobals.curl_command then `Curl + else if command_exists "wget" then `Wget + else + OpamGlobals.error_and_exit + "Could not find a suitable download command. Please make sure you have \ + either \"curl\" or \"wget\" installed, or specify a custom command \ + through variable OPAMFETCH." + let download_command = let retry = string_of_int OpamGlobals.download_retry in let wget ~compress:_ dir src = @@ -702,16 +716,21 @@ let download_command = OpamMisc.fatal e; internal_error "curl: code %s while downloading %s" code src in + let custom dl_cmd ~compress dir src = + let dst = Filename.basename src in + match dl_cmd ~url:src ~out:dst ~retry:OpamGlobals.download_retry ~compress + with + | cmd::args -> + make_command ~dir cmd args @@> fun r -> + raise_on_process_error r; + Done () + | [] -> internal_error "Empty custom download command" + in lazy ( - match OpamGlobals.curl_command with - | Some cmd -> curl cmd - | None -> - if command_exists "curl" then - curl "curl" - else if command_exists "wget" then - wget - else - OpamGlobals.error_and_exit "Cannot find curl nor wget." + match choose_download_tool () with + | `Wget -> wget + | `Curl -> curl OpamGlobals.curl_command + | `Custom cust -> custom cust ) let really_download ~overwrite ?(compress=false) ~src ~dst = diff --git a/src/solver/opamCudf.ml b/src/solver/opamCudf.ml index d5a35d327b6..ba1f11d4294 100644 --- a/src/solver/opamCudf.ml +++ b/src/solver/opamCudf.ml @@ -454,36 +454,31 @@ let to_cudf univ req = ( req_extra = [] } ) +let external_solver_name () = + match OpamGlobals.external_solver ~input:"" ~output:"" ~criteria:"" with + | cmd::_ -> cmd + | [] -> raise Not_found + let external_solver_exists = lazy ( - let ex = OpamSystem.command_exists (OpamGlobals.get_external_solver ()) in - if not ex && !OpamGlobals.use_external_solver && - !OpamGlobals.external_solver <> None - then - OpamGlobals.error_and_exit - "You specified you wanted to use external solver %s, but it cannot be found.\n\ - Fix your installation, your configuration or use '--use-internal-solver'." - (OpamGlobals.get_external_solver ()) - else ex + try + let name = external_solver_name () in + let ex = OpamSystem.command_exists name in + if not ex && !OpamGlobals.use_external_solver && + !OpamGlobals.env_external_solver <> None + then + OpamGlobals.error_and_exit + "Your configuration or environment specifies external solver %s, but \ + it cannot be found. Fix your installation, your configuration or \ + use '--use-internal-solver'." + name + else ex + with Not_found -> false ) let external_solver_available () = !OpamGlobals.use_external_solver && (Lazy.force external_solver_exists) -let external_solver_command ~input ~output ~criteria = - let s = OpamGlobals.get_external_solver () in - match Filename.basename s with - | "packup" -> - [s; - OpamFilename.to_string input; - OpamFilename.to_string output; - "-u"; criteria] - | "aspcud" | _ -> - [s; - OpamFilename.to_string input; - OpamFilename.to_string output; - criteria] - let solver_calls = ref 0 let dump_universe oc univ = @@ -500,10 +495,8 @@ let dump_cudf_request ~extern ~version_map (_, univ,_ as cudf) criteria = let oc = open_out filename in if extern then Printf.fprintf oc "# %s\n" - (String.concat " " ( - external_solver_command - ~input:(OpamFilename.of_string "$in") - ~output:(OpamFilename.of_string "$out") ~criteria)) + (String.concat " " + (OpamGlobals.external_solver ~input:"$in" ~output:"$out" ~criteria)) else Printf.fprintf oc "#internal OPAM solver\n"; Cudf_printer.pp_cudf oc cudf; @@ -544,7 +537,10 @@ let dose_solver_callback ~criteria (_,universe,_ as cudf) = in OpamSystem.command ~verbose:(!OpamGlobals.debug_level >= 2) - (external_solver_command ~input:solver_in ~output:solver_out ~criteria); + (OpamGlobals.external_solver + ~input:(OpamFilename.to_string solver_in) + ~output:(OpamFilename.to_string solver_out) + ~criteria); OpamFilename.remove solver_in; if not (OpamFilename.exists solver_out) then raise (Common.CudfSolver.Error "no output") @@ -580,7 +576,7 @@ let check_cudf_version = (* Run with closed stdin to workaround bug in some solver scripts *) match OpamSystem.read_command_output ~verbose:false ~allow_stdin:false - [OpamGlobals.get_external_solver(); "-v"] + [external_solver_name (); "-v"] with | [] -> log "No response from 'solver -v', using compat criteria";