Permalink
Browse files

Fix a bad bug with wrong environment setting.

Sometime, it 'opam config env' hadn't been called in the current shell, some package build was failing miserably. This commit clean-up a lot of small things in the management of environements, so now 'opam install XXX' should always work even if the user has a wrong environment set-upt.
  • Loading branch information...
1 parent 396f0b5 commit e65ff1bce9249eea3c858f8181ee0cc0fadb544d @samoht samoht committed Jan 7, 2013
@@ -240,23 +240,15 @@ let config_compil t c =
log "OUTPUT: %S" output;
OpamGlobals.msg "%s\n" output
-let empty_env = {
- add_to_env = [];
- add_to_path = OpamFilename.raw_dir "";
- new_env = []
-}
-
let print_env env =
- if env <> empty_env then
- List.iter (fun (k,v) ->
- OpamGlobals.msg "%s=%s; export %s;\n" k v k;
- ) env.new_env
+ List.iter (fun (k,v) ->
+ OpamGlobals.msg "%s=%s; export %s;\n" k v k;
+ ) env
let print_csh_env env =
- if env <> empty_env then
- List.iter (fun (k,v) ->
- OpamGlobals.msg "setenv %s %S;\n" k v;
- ) env.new_env
+ List.iter (fun (k,v) ->
+ OpamGlobals.msg "setenv %s %S;\n" k v;
+ ) env
let config request =
log "config %s" (string_of_config request);
View
@@ -227,7 +227,7 @@ let string_of_commands commands =
let compilation_env t opam =
let env0 = OpamState.get_env t in
- OpamState.update_env t env0 (OpamFile.OPAM.build_env opam)
+ OpamState.add_to_env t env0 (OpamFile.OPAM.build_env opam)
let proceed_to_delete ~rm_build t nv =
log "deleting %s" (OpamPackage.to_string nv);
@@ -264,11 +264,7 @@ let proceed_to_delete ~rm_build t nv =
else t.root in
try
OpamGlobals.msg "%s\n" (string_of_commands remove);
- OpamFilename.exec
- ~add_to_env:env.add_to_env
- ~add_to_path:[OpamPath.Switch.bin t.root t.switch]
- exec_dir
- remove
+ OpamFilename.exec ~env exec_dir remove
with _ ->
();
);
@@ -388,17 +384,13 @@ let proceed_to_change t nv_old nv =
(* Generate an environnement file *)
let env_f = OpamPath.Switch.build_env t.root t.switch nv in
- OpamFile.Env.write env_f env.new_env;
+ OpamFile.Env.write env_f env;
(* Exec the given commands. *)
let exec name f =
let commands = OpamState.filter_commands t (f opam) in
OpamGlobals.msg "%s:\n%s\n" name (string_of_commands commands);
- OpamFilename.exec
- ~add_to_env:env.add_to_env
- ~add_to_path:[env.add_to_path]
- p_build
- commands in
+ OpamFilename.exec ~env p_build commands in
try
(* First, we build the package. *)
exec ("Building " ^ OpamPackage.to_string nv) OpamFile.OPAM.build;
View
@@ -604,7 +604,7 @@ let filter_command t (l, f) =
let filter_commands t l =
OpamMisc.filter_map (filter_command t) l
-let expand_env t env =
+let expand_env t (env: env_updates) : env =
List.map (fun (ident, symbol, string) ->
let string = substitute_string t string in
let read_env () =
@@ -620,43 +620,37 @@ let expand_env t env =
| _ -> failwith (Printf.sprintf "expand_env: %s is an unknown symbol" symbol)
) env
-let update_env t env e =
- let expanded = expand_env t e in
- { env with
- add_to_env = expanded @ env.add_to_env;
- new_env = expanded @ env.new_env }
+let add_to_env t (env: env) (updates: env_updates) =
+ let env = List.filter (fun (k,_) -> List.for_all (fun (u,_,_) -> u <> k) updates) env in
+ env @ expand_env t updates
let get_env t =
let comp = compiler t t.compiler in
let add_to_path = OpamPath.Switch.bin t.root t.switch in
let new_path = "PATH", "+=", OpamFilename.Dir.to_string add_to_path in
-
- let add_to_env = OpamFile.Comp.env comp in
let toplevel_dir =
"OCAML_TOPLEVEL_PATH", "=", OpamFilename.Dir.to_string (OpamPath.Switch.toplevel t.root t.switch) in
let man_path =
"MANPATH", ":=", OpamFilename.Dir.to_string (OpamPath.Switch.man_dir t.root t.switch) in
- let new_env = new_path :: man_path :: toplevel_dir :: add_to_env in
-
- let add_to_env = expand_env t add_to_env in
- let new_env = expand_env t new_env in
-
- (* if --root <dir> is passed on the command line, or if OPAMROOT is set. *)
- let new_env =
+ let comp_env = OpamFile.Comp.env comp in
+ let root =
if !OpamGlobals.root_dir <> OpamGlobals.default_opam_dir then
- ("OPAMROOT", !OpamGlobals.root_dir) :: new_env
+ [ "OPAMROOT", "=", !OpamGlobals.root_dir ]
else
- new_env in
+ [] in
+
+ let updates = new_path :: man_path :: toplevel_dir :: (root @ comp_env) in
+ let env0 = OpamMisc.env () in
- { add_to_env; add_to_path; new_env }
+ add_to_env t env0 updates
let print_env_warning ?(add_profile = false) t =
match
List.filter
(fun (s, v) ->
Some v <> try Some (OpamMisc.getenv s) with _ -> None)
- (get_env t).new_env
+ (get_env t)
with
| [] -> () (* every variables are correctly set *)
| l ->
View
@@ -91,7 +91,7 @@ val unknown_compiler: compiler -> 'a
val get_env: state -> env
(** Update an environment. *)
-val update_env: state -> env -> (string * string * string) list -> env
+val add_to_env: state -> env -> (string * string * string) list -> env
(** Print a warning if the environment is not set-up properly. *)
val print_env_warning: ?add_profile:bool -> state -> unit
View
@@ -1104,7 +1104,7 @@ module Env = struct
let internal = "env"
- type t = (string * string) list
+ type t = env
let empty = []
View
@@ -199,7 +199,7 @@ module Reinstall: IO_FILE with type t = package_set
module Updated: IO_FILE with type t = package_set
(** Environement variables *)
-module Env: IO_FILE with type t = (string * string) list
+module Env: IO_FILE with type t = env
(** Compiler version [$opam/compilers/] *)
module Comp: sig
View
@@ -60,13 +60,12 @@ let in_dir dirname fn =
else
OpamGlobals.error_and_exit "%s does not exist!" dirname
-let exec dirname ?(add_to_env=[]) ?(add_to_path=[]) cmds =
+let exec dirname ?env cmds =
+ let env = match env with
+ | None -> None
+ | Some l -> Some (Array.of_list (List.map (fun (k,v) -> k^"="^v) l)) in
in_dir dirname
- (fun () ->
- OpamSystem.commands
- ~add_to_env
- ~add_to_path:(List.map Dir.of_string add_to_path)
- cmds)
+ (fun () -> OpamSystem.commands ?env cmds)
let move_dir src dst =
OpamSystem.command [ "mv"; Dir.to_string src; Dir.to_string dst ]
@@ -37,9 +37,7 @@ val list_dirs: Dir.t -> Dir.t list
val in_dir: Dir.t -> (unit -> 'a) -> 'a
(** Execute a list of commands in a given directory *)
-val exec: Dir.t
- -> ?add_to_env:(string * string) list
- -> ?add_to_path:Dir.t list -> string list list -> unit
+val exec: Dir.t -> ?env:(string * string) list -> string list list -> unit
(** Move a directory *)
val move_dir: Dir.t -> Dir.t -> unit
View
@@ -256,6 +256,8 @@ let env = lazy (
let getenv n =
List.assoc n (Lazy.force env)
+let env () = Lazy.force env
+
let indent_left s nb =
let nb = nb - String.length s in
if nb <= 0 then
View
@@ -210,70 +210,63 @@ let real_path p =
else
dir / base
)
-
-let replace_path bins =
- let path = ref "<not set>" in
- let env = Unix.environment () in
- for i = 0 to Array.length env - 1 do
- let k,v = match OpamMisc.cut_at env.(i) '=' with
- | Some (k,v) -> k,v
- | None -> assert false in
- if k = "PATH" then (
- let bins = List.filter Sys.file_exists bins in
- let new_path = String.concat ":" bins in
- env.(i) <- "PATH=" ^ new_path;
- path := new_path;
- )
- done;
- env, !path
-
-let get_current_path () =
- try OpamMisc.split (OpamMisc.getenv "PATH") ':'
- with Not_found -> []
-
type command = string list
-let run_process ?verbose ?path ?(add_to_env=[]) ?(add_to_path=[]) = function
+let default_env =
+ Unix.environment ()
+
+let reset_env = lazy (
+ let env = OpamMisc.env () in
+ let env =
+ List.map (fun (k,v as c) ->
+ match k with
+ | "PATH" -> k, String.concat ":" (OpamMisc.reset_env_value ~prefix:!OpamGlobals.root_dir v)
+ | _ -> c
+ ) env in
+ let env = List.map (fun (k,v) -> k^"="^v) env in
+ Array.of_list env
+)
+
+let run_process ?verbose ?(env=default_env) = function
| [] -> invalid_arg "run_process"
| cmd :: args ->
- let env, path =
- match path with
- | None -> replace_path (add_to_path @ get_current_path ())
- | Some p -> replace_path p in
- let add_to_env = List.map (fun (k,v) -> k^"="^v) add_to_env in
- let env = Array.concat [ env; Array.of_list add_to_env ] in
- let name = log_file () in
- mkdir (Filename.dirname name);
- let str = String.concat " " (cmd :: args) in
- log "[%s] %s" (Filename.basename name) str;
- if None <> try Some (String.index cmd ' ') with Not_found -> None then
- OpamGlobals.warning "Command %S contains 1 space" cmd;
+
+ (* Set-up the log files *)
+ let name = log_file () in
+ mkdir (Filename.dirname name);
+ let str = String.concat " " (cmd :: args) in
+ log "[%s] %s" (Filename.basename name) str;
+
+ (* Check that the command doesn't contain whitespaces *)
+ if None <> try Some (String.index cmd ' ') with Not_found -> None then
+ OpamGlobals.warning "Command %S contains 1 space" cmd;
+
+ (* Display a user-friendly message if the command does not exists *)
+ let cmd_exists =
+ OpamProcess.run ~env ~name:(log_file ()) ~verbose:false "which" [cmd] in
+ OpamProcess.clean_files cmd_exists;
+
+ if OpamProcess.is_success cmd_exists then (
let verbose = match verbose with
| None -> !OpamGlobals.debug || !OpamGlobals.verbose
| Some b -> b in
- let cmd_exists =
- OpamProcess.run ~env ~name:(log_file ()) ~verbose:false "which" [cmd] in
- OpamProcess.clean_files cmd_exists;
- if OpamProcess.is_success cmd_exists then (
- let r = OpamProcess.run ~env ~name ~verbose cmd args in
- if not !OpamGlobals.debug then
- OpamProcess.clean_files r;
- r
- ) else
- internal_error "%S: command not found\n" cmd
-
-let command ?verbose ?(add_to_env=[]) ?(add_to_path=[]) cmd =
- let r = run_process ?verbose ~add_to_env ~add_to_path cmd in
- if OpamProcess.is_success r then
- ()
- else
+ let r = OpamProcess.run ~env ~name ~verbose cmd args in
+ if not !OpamGlobals.debug then
+ OpamProcess.clean_files r;
+ r
+ ) else
+ internal_error "%S: command not found\n" cmd
+
+let command ?verbose ?env cmd =
+ let r = run_process ?verbose ?env cmd in
+ if not (OpamProcess.is_success r) then
process_error r
-let commands ?verbose ?(add_to_env=[]) ?(add_to_path = []) commands =
- List.iter (command ?verbose ~add_to_env ~add_to_path) commands
+let commands ?verbose ?env commands =
+ List.iter (command ?verbose ?env) commands
-let read_command_output ?verbose ?path cmd =
- let r = run_process ?verbose ?path cmd in
+let read_command_output ?verbose ?env cmd =
+ let r = run_process ?verbose ?env cmd in
if OpamProcess.is_success r then
r.OpamProcess.r_stdout
else
@@ -325,7 +318,7 @@ module Tar = struct
let extract_function file =
let command c dir =
- command [ "tar" ; Printf.sprintf "xf%c" c ; file; "-C" ; dir ] in
+ command [ "tar" ; Printf.sprintf "xf%c" c ; file; "-C" ; dir ] in
let ext =
List.fold_left
@@ -430,13 +423,10 @@ let ocaml_version = lazy (
None
)
+(* Reset the path to get the system compiler *)
let system command = lazy (
try
- let path =
- try OpamMisc.getenv "PATH"
- with Not_found -> "" in
- let path = OpamMisc.reset_env_value ~prefix:!OpamGlobals.root_dir path in
- match read_command_output ~verbose:false ~path command with
+ match read_command_output ~verbose:false ~env:(Lazy.force reset_env) command with
| h::_ -> Some (OpamMisc.strip h)
| [] -> internal_error "ocamlc -where"
with _ ->
View
@@ -92,27 +92,17 @@ val directories_with_links: string -> string list
(** a command is a list of words *)
type command = string list
-(** [command cmd] executes the command [cmd]. Return the exit code. *)
-val command:
- ?verbose:bool ->
- ?add_to_env:(string*string) list ->
- ?add_to_path:string list -> command -> unit
-
-(** [commands ~add_to_path cmds] executes the commands [cmds]
- in a context where $PATH contains [add_to_path] at the beginning.
- It stops whenever one command fails. *)
-val commands:
- ?verbose:bool ->
- ?add_to_env:(string*string) list ->
- ?add_to_path:string list -> command list -> unit
-
-(** [read_command_output cmd] executes the command [cmd] and return
- the lines from stdout *)
-val read_command_output:
- ?verbose:bool ->
- ?path:string list
- -> command
- -> string list
+(** [command cmd] executes the command [cmd] in the correct OPAM
+ environment. Return the exit code. *)
+val command: ?verbose:bool -> ?env:string array -> command -> unit
+
+(** [commands cmds] executes the commands [cmds] in the correct
+ OPAM environment. It stops whenever one command fails. *)
+val commands: ?verbose:bool -> ?env:string array -> command list -> unit
+
+(** [read_command_output cmd] executes the command [cmd] in the
+ correct OPAM environment and return the lines from stdout *)
+val read_command_output: ?verbose:bool -> ?env:string array -> command -> string list
(** Test whether the file is an archive, by looking as its extension *)
val is_tar_archive: string -> bool
View
@@ -432,11 +432,9 @@ type 'a request = {
wish_upgrade: 'a conjunction;
}
-type env = {
- add_to_env : (string * string) list;
- add_to_path: dirname;
- new_env : (string * string) list;
-}
+type env = (string * string) list
+
+type env_updates = (string * string * string) list
type user_action =
| Install
Oops, something went wrong.

0 comments on commit e65ff1b

Please sign in to comment.