Source file 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
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 load lock_kind =
let root = OpamStateConfig.(!r.root_dir) in
log "LOAD-GLOBAL-STATE @ %a" (slog OpamFilename.Dir.to_string) root;
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
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))),
"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)
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