Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
opamGlobalState.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
(**************************************************************************) (* *) (* Copyright 2012-2015 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved. This file is distributed under the terms of the *) (* GNU Lesser General Public License version 2.1, with the special *) (* exception on linking described in the file LICENSE. *) (* *) (**************************************************************************) open OpamTypes open OpamStd.Op open OpamFilename.Op open OpamStateTypes let log fmt = OpamConsole.log "GSTATE" fmt let slog = OpamConsole.slog let load_config global_lock root = let config = match OpamStateConfig.load root with | Some c -> c | None -> if OpamFilename.exists (root // "aliases") then OpamFile.Config.(with_opam_version (OpamVersion.of_string "1.1") empty) else OpamConsole.error_and_exit `Configuration_error "%s exists, but does not appear to be a valid opam root. Please \ remove it and use `opam init', or specify a different `--root' \ argument" (OpamFilename.Dir.to_string root) in OpamFormatUpgrade.as_necessary global_lock root config; config let inferred_from_system = "Inferred from system" let load lock_kind = let root = OpamStateConfig.(!r.root_dir) in log "LOAD-GLOBAL-STATE @ %a" (slog OpamFilename.Dir.to_string) root; (* Always take a global read lock, this is only used to prevent concurrent ~/.opam format changes *) let has_root = OpamFilename.exists_dir root in let global_lock = if has_root then OpamFilename.flock `Lock_read (OpamPath.lock root) else OpamSystem.lock_none in (* The global_state lock actually concerns the global config file only (and the consistence thereof with the repository and switch sets, and the currently installed shell init scripts) *) if not has_root then OpamConsole.error_and_exit `Configuration_error "Opam has not been initialised, please run `opam init'"; let config_lock = OpamFilename.flock lock_kind (OpamPath.config_lock root) in let config = load_config global_lock root in let switches = List.filter (fun sw -> not (OpamSwitch.is_external sw) || OpamFilename.exists_dir (OpamSwitch.get_root root sw)) (OpamFile.Config.installed_switches config) in let config = OpamFile.Config.with_installed_switches switches config in let global_variables = List.fold_left (fun acc (v,value) -> OpamVariable.Map.add v (lazy (Some (OpamStd.Option.default (S "unknown") (Lazy.force value))), (* Careful on changing it, it is used to determine user defined variables on `config report`. See [OpamConfigCommand.help]. *) inferred_from_system) acc) OpamVariable.Map.empty (OpamSysPoll.variables) in let global_variables = List.fold_left (fun acc (v,value,doc) -> OpamVariable.Map.add v (lazy (Some value), doc) acc) global_variables (OpamFile.Config.global_variables config) in let eval_variables = OpamFile.Config.eval_variables config in let global_variables = let env = lazy (OpamEnv.get_pure () |> OpamTypesBase.env_array) in List.fold_left (fun acc (v, cmd, doc) -> OpamVariable.Map.update v (fun previous_value -> (lazy (try let ret = OpamSystem.read_command_output ~env:(Lazy.force env) ~allow_stdin:false cmd in Some (S (OpamStd.String.strip (String.concat "\n" ret))) with e -> OpamStd.Exn.fatal e; log "Failed to evaluate global variable %a: %a" (slog OpamVariable.to_string) v (slog Printexc.to_string) e; Lazy.force (fst previous_value))), doc) (lazy None, "") acc) global_variables eval_variables in { global_lock = config_lock; root; config; global_variables; } let switches gt = OpamFile.Config.installed_switches gt.config let fold_switches f gt acc = List.fold_left (fun acc switch -> f switch (OpamFile.SwitchSelections.safe_read (OpamPath.Switch.selections gt.root switch)) acc ) acc (OpamFile.Config.installed_switches gt.config) let switch_exists gt switch = if OpamSwitch.is_external switch then OpamStateConfig.local_switch_exists gt.root switch else List.mem switch (switches gt) let all_installed gt = fold_switches (fun _ sel acc -> OpamPackage.Set.union acc sel.sel_installed) gt OpamPackage.Set.empty let installed_versions gt name = fold_switches (fun switch sel acc -> let installed = OpamPackage.packages_of_name sel.sel_installed name in try let nv = OpamPackage.Set.choose installed in try OpamPackage.Map.add nv (switch::OpamPackage.Map.find nv acc) acc with Not_found -> OpamPackage.Map.add nv [switch] acc with Not_found -> acc) gt OpamPackage.Map.empty let repos_list gt = OpamFile.Config.repositories gt.config let unlock gt = OpamSystem.funlock gt.global_lock; (gt :> unlocked global_state) let with_write_lock ?dontblock gt f = let ret, gt = OpamFilename.with_flock_upgrade `Lock_write ?dontblock gt.global_lock @@ fun _ -> f ({ gt with global_lock = gt.global_lock } : rw global_state) (* We don't actually change the field value, but this makes restricting the phantom lock type possible*) in ret, { gt with global_lock = gt.global_lock } let with_ lock f = let gt = load lock in try let r = f gt in ignore (unlock gt); r with e -> OpamStd.Exn.finalise e (fun () -> ignore (unlock gt)) let write gt = OpamFile.Config.write (OpamPath.config gt.root) gt.config let fix_switch_list gt = let known_switches0 = switches gt in let known_switches = match OpamStateConfig.get_switch_opt () with | None -> known_switches0 | Some sw -> if List.mem sw known_switches0 || not (switch_exists gt sw) then known_switches0 else sw::known_switches0 in let known_switches = List.filter (switch_exists gt) known_switches in if known_switches = known_switches0 then gt else let config = OpamFile.Config.with_installed_switches known_switches gt.config in let gt = { gt with config } in if not OpamCoreConfig.(!r.safe_mode) then try snd @@ with_write_lock ~dontblock:true gt @@ fun gt -> write gt, gt with OpamSystem.Locked -> gt else gt