diff --git a/src/client/opamArg.ml b/src/client/opamArg.ml index c43ff1f6382..29d75df455d 100644 --- a/src/client/opamArg.ml +++ b/src/client/opamArg.ml @@ -543,6 +543,7 @@ let apply_global_options cli o = (* ?solver_preferences_best_effort_prefix: *) (* - state options - *) ?root_dir:o.opt_root + ?original_root_dir:o.opt_root ?current_switch:(o.opt_switch >>| OpamSwitch.of_string) ?switch_from:(o.opt_switch >>| fun _ -> `Command_line) (* ?jobs: int *) diff --git a/src/client/opamCliMain.ml b/src/client/opamCliMain.ml index 2ddf5ff7b3e..75e953335a1 100644 --- a/src/client/opamCliMain.ml +++ b/src/client/opamCliMain.ml @@ -181,7 +181,7 @@ let check_and_run_external_commands () = let yes = if yes then Some (Some true) else None in OpamCoreConfig.init ?yes ?confirm_level (); OpamFormatConfig.init (); - let root_dir = OpamStateConfig.opamroot () in + let root_from, root_dir = OpamStateConfig.opamroot () in let has_init, root_upgraded = match OpamStateConfig.load_defaults ~lock_kind:`Lock_read root_dir with | None -> (false, false) @@ -210,7 +210,7 @@ let check_and_run_external_commands () = env_update_resolved "PATH" PlusEq (OpamFilename.Dir.to_string plugins_bin) ] in - OpamStateConfig.init ~root_dir (); + OpamStateConfig.init ~root_from ~root_dir (); match OpamStateConfig.get_switch_opt () with | None -> env_array (OpamEnv.get_pure ~updates ()) | Some sw -> diff --git a/src/client/opamClientConfig.ml b/src/client/opamClientConfig.ml index 9f1571cde86..5e4c6a09e74 100644 --- a/src/client/opamClientConfig.ml +++ b/src/client/opamClientConfig.ml @@ -209,7 +209,7 @@ let opam_init ?root_dir ?strict ?solver = let open OpamStd.Option.Op in (* (i) get root dir *) - let root = OpamStateConfig.opamroot ?root_dir () in + let root_from, root = OpamStateConfig.opamroot ?root_dir () in (* (ii) load conf file and set defaults *) (* the init for OpamFormat is done in advance since (a) it has an effect on @@ -261,5 +261,5 @@ let opam_init ?root_dir ?strict ?solver = OpamCoreConfig.initk ?log_dir |> OpamRepositoryConfig.initk |> OpamSolverConfig.initk ?solver |> - OpamStateConfig.initk ~root_dir:root |> + OpamStateConfig.initk ~root_dir:root ~root_from |> initk diff --git a/src/client/opamCommands.ml b/src/client/opamCommands.ml index dc72f544ff3..3e55a67628f 100644 --- a/src/client/opamCommands.ml +++ b/src/client/opamCommands.ml @@ -94,7 +94,7 @@ let global_options cli = switch_to_updated_self OpamStd.Option.Op.(options.debug_level ++ OpamCoreConfig.E.debug () +! 0 |> abs > 0) - (OpamStateConfig.opamroot ?root_dir:options.opt_root ()); + (snd (OpamStateConfig.opamroot ?root_dir:options.opt_root ())); let root_is_ok = OpamStd.Option.default false (OpamClientConfig.E.rootisok ()) in diff --git a/src/state/opamStateConfig.ml b/src/state/opamStateConfig.ml index b1fa359c07e..1314c1154b9 100644 --- a/src/state/opamStateConfig.ml +++ b/src/state/opamStateConfig.ml @@ -54,6 +54,7 @@ end type t = { root_dir: OpamFilename.Dir.t; original_root_dir: OpamFilename.Dir.t; + root_from: provenance; current_switch: OpamSwitch.t option; switch_from: provenance; jobs: int Lazy.t; @@ -70,24 +71,26 @@ type t = { no_depexts: bool; } +let default_root = + (* On Windows, if a .opam directory is found in %HOME% or %USERPROFILE% then + then we'll use it. Otherwise, we use %LOCALAPPDATA%. *) + let home_location = + let open OpamFilename in + concat_and_resolve (Dir.of_string (OpamStd.Sys.home ())) ".opam" + in + if not Sys.win32 || OpamFilename.exists_dir home_location then + home_location + else + let open OpamFilename in + let local_appdata = + Dir.of_string (OpamStubs.getPathToLocalAppData ()) + in + concat_and_resolve local_appdata "opam" + let default = { - root_dir = ( - (* On Windows, if a .opam directory is found in %HOME% or %USERPROFILE% then - then we'll use it. Otherwise, we use %LOCALAPPDATA%. *) - let home_location = - let open OpamFilename in - concat_and_resolve (Dir.of_string (OpamStd.Sys.home ())) ".opam" - in - if not Sys.win32 || OpamFilename.exists_dir home_location then - home_location - else - let open OpamFilename in - let local_appdata = - Dir.of_string (OpamStubs.getPathToLocalAppData ()) - in - concat_and_resolve local_appdata "opam" - ); - original_root_dir = default_root (); + root_dir = default_root; + original_root_dir = default_root; + root_from = `Default; current_switch = None; switch_from = `Default; jobs = lazy (max 1 (OpamSysPoll.cores () - 1)); @@ -111,6 +114,7 @@ let default = { type 'a options_fun = ?root_dir:OpamFilename.Dir.t -> ?original_root_dir:OpamFilename.Dir.t -> + ?root_from:provenance -> ?current_switch:OpamSwitch.t -> ?switch_from:provenance -> ?jobs:(int Lazy.t) -> @@ -130,6 +134,7 @@ type 'a options_fun = let setk k t ?root_dir ?original_root_dir + ?root_from ?current_switch ?switch_from ?jobs @@ -149,6 +154,7 @@ let setk k t k { root_dir = t.root_dir + root_dir; original_root_dir = t.original_root_dir + original_root_dir; + root_from = t.root_from + root_from; current_switch = (match current_switch with None -> t.current_switch | s -> s); switch_from = t.switch_from + switch_from; @@ -174,14 +180,22 @@ let update ?noop:_ = setk (fun cfg () -> r := cfg) !r let initk k = let open OpamStd.Option.Op in + let root_dir, original_root_dir, root_from = + match E.root () with + | None -> None, None, None + | Some root -> + let root = OpamFilename.Dir.of_string root in + Some root, Some root, Some `Env + in let current_switch, switch_from = match E.switch () with | Some "" | None -> None, None | Some s -> Some (OpamSwitch.of_string s), Some `Env in setk (setk (fun c -> r := c; k)) !r - ?root_dir:(E.root () >>| OpamFilename.Dir.of_string) - ?original_root_dir:(E.root () >>| OpamFilename.Dir.of_string) + ?root_dir + ?original_root_dir + ?root_from ?current_switch ?switch_from ?jobs:(E.jobs () >>| fun s -> lazy s) @@ -204,10 +218,14 @@ let initk k = let init ?noop:_ = initk (fun () -> ()) let opamroot ?root_dir () = - let open OpamStd.Option.Op in - (root_dir >>+ fun () -> - OpamStd.Env.getopt "OPAMROOT" >>| OpamFilename.Dir.of_string) - +! default.root_dir + match root_dir with + | Some root -> `Command_line, root + | None -> + match OpamStd.Env.getopt "OPAMROOT" with + | Some root -> + `Env, OpamFilename.Dir.of_string root + | None -> + `Default, default.root_dir let is_newer_raw = function | Some v -> diff --git a/src/state/opamStateConfig.mli b/src/state/opamStateConfig.mli index e5221e827ed..4531767b049 100644 --- a/src/state/opamStateConfig.mli +++ b/src/state/opamStateConfig.mli @@ -39,6 +39,7 @@ end type t = private { root_dir: OpamFilename.Dir.t; original_root_dir: OpamFilename.Dir.t; + root_from: provenance; current_switch: OpamSwitch.t option; switch_from: provenance; jobs: int Lazy.t; @@ -58,6 +59,7 @@ type t = private { type 'a options_fun = ?root_dir:OpamFilename.Dir.t -> ?original_root_dir:OpamFilename.Dir.t -> + ?root_from:provenance -> ?current_switch:OpamSwitch.t -> ?switch_from:provenance -> ?jobs:(int Lazy.t) -> @@ -84,7 +86,7 @@ val default : t (** Get the initial opam root value (from default, env or optional argument). This allows one to get it before doing the init, which is useful to get the configuration file used to fill some options to init() *) -val opamroot: ?root_dir:dirname -> unit -> dirname +val opamroot: ?root_dir:dirname -> unit -> provenance * dirname (** Loads the global configuration file, protecting against concurrent writes *) val load: ?lock_kind: 'a lock -> dirname -> OpamFile.Config.t option