Source file opamRepositoryCommand.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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
open OpamTypes
open OpamStateTypes
open OpamStd.Op
let log fmt = OpamConsole.log "REPOSITORY" fmt
let update_global_selection gt update_fun =
let repos = OpamFile.Config.repositories gt.config in
let config = OpamFile.Config.with_repositories (update_fun repos) gt.config in
let gt = { gt with config } in
OpamGlobalState.write gt;
gt
let update_selection gt ~global ~switches update_fun =
List.iter (OpamSwitchState.update_repositories gt update_fun) switches;
if global then
(List.iter (fun sw ->
if not (List.mem sw switches) then
OpamSwitchState.update_repositories gt (fun r -> r) sw)
(OpamFile.Config.installed_switches gt.config);
let (), gt =
OpamGlobalState.with_write_lock gt @@ fun gt ->
(), update_global_selection gt update_fun
in
gt)
else gt
let update_repos_config rt repositories =
let repo_opams =
OpamRepositoryName.Map.filter (fun name _ ->
OpamRepositoryName.Map.find_opt name rt.repositories =
OpamRepositoryName.Map.find_opt name repositories)
rt.repo_opams
in
let rt = { rt with repositories; repo_opams } in
OpamRepositoryState.Cache.remove ();
OpamRepositoryState.write_config rt;
rt
let add rt name url trust_anchors =
log "repository-add";
let root = rt.repos_global.root in
let repo_exists =
OpamStd.Option.of_Not_found
(OpamRepositoryName.Map.find name) rt.repositories
in
match repo_exists with
| Some r when r.repo_url = url &&
(trust_anchors = r.repo_trust || trust_anchors = None)
-> rt
| Some r ->
OpamConsole.error_and_exit `Bad_arguments
"Repository %s is already set up%s. To change that, use 'opam \
repository set-url %s %s'."
(OpamRepositoryName.to_string name)
(if r.repo_url <> url then
" and points to "^OpamUrl.to_string r.repo_url
else match r.repo_trust with
| None -> " without trust anchors"
| Some ta ->
Printf.sprintf " with trust anchors %s and quorum %d"
(OpamStd.List.concat_map ~nil:"()" "," String.escaped
ta.fingerprints)
ta.quorum)
(OpamRepositoryName.to_string name)
(OpamUrl.to_string url)
| None ->
let repo = { repo_name = name; repo_url = url;
repo_trust = trust_anchors; }
in
if OpamFilename.exists_dir (OpamRepositoryPath.root root name) ||
OpamFilename.exists (OpamRepositoryPath.tar root name)
then
OpamConsole.error_and_exit `Bad_arguments
"Invalid repository name, %s exists"
(OpamFilename.Dir.to_string (OpamRepositoryPath.root root name));
if url.OpamUrl.backend = `rsync &&
OpamUrl.local_dir url <> None &&
OpamUrl.local_dir (OpamRepositoryPath.Remote.packages_url url)
= None &&
not (OpamConsole.confirm
"%S doesn't contain a \"packages\" directory.\n\
Is it really the directory of your repo?"
(OpamUrl.to_string url))
then OpamStd.Sys.exit_because `Aborted;
update_repos_config rt
(OpamRepositoryName.Map.add name repo rt.repositories)
let remove rt name =
log "repository-remove";
let rt =
update_repos_config rt (OpamRepositoryName.Map.remove name rt.repositories)
in
OpamRepositoryState.Cache.save rt;
OpamFilename.rmdir (OpamRepositoryPath.root rt.repos_global.root name);
OpamFilename.remove (OpamRepositoryPath.tar rt.repos_global.root name);
rt
let set_url rt name url trust_anchors =
log "repository-set-url";
let repo =
try OpamRepositoryName.Map.find name rt.repositories
with Not_found ->
OpamConsole.error_and_exit `Not_found "No repository %s found"
(OpamRepositoryName.to_string name);
in
OpamFilename.cleandir (OpamRepositoryPath.root rt.repos_global.root name);
OpamFilename.remove (OpamRepositoryPath.tar rt.repos_global.root name);
let repo = { repo with repo_url = url; repo_trust = trust_anchors; } in
OpamRepositoryState.remove_from_repos_tmp rt name;
update_repos_config rt (OpamRepositoryName.Map.add name repo rt.repositories)
let print_selection rt ~short repos_list =
if short then
List.iter
(fun r -> OpamConsole.msg "%s\n" (OpamRepositoryName.to_string r))
repos_list
else
List.mapi (fun i name -> [
Printf.sprintf "%2d" (i+1);
OpamRepositoryName.to_string name |> OpamConsole.colorise `bold;
try
let r = OpamRepositoryName.Map.find name rt.repositories in
if r.repo_url = OpamUrl.empty then "-" else
OpamUrl.to_string r.repo_url |> OpamConsole.colorise `underline
with Not_found -> "not found" |> OpamConsole.colorise `red
])
repos_list |>
OpamStd.Format.align_table |>
OpamConsole.print_table stdout ~sep:" "
let switch_repos rt sw =
let switch_config =
OpamStateConfig.Switch.safe_load
~lock_kind:`Lock_read rt.repos_global sw
in
match switch_config.OpamFile.Switch_config.repos with
| None -> OpamGlobalState.repos_list rt.repos_global
| Some rl -> rl
let list rt ~global ~switches ~short =
if global then
(let repos = OpamGlobalState.repos_list rt.repos_global in
if not short then
OpamConsole.header_msg
"Default repository configuration (for newly created switches)";
print_selection rt ~short repos);
List.iter (fun sw ->
if not short then
OpamConsole.header_msg
"Repository configuration for switch %s" (OpamSwitch.to_string sw);
print_selection rt ~short (switch_repos rt sw))
switches
let list_all rt ~short =
log "repository-list";
if short then
OpamRepositoryName.Map.iter
(fun r _ ->
OpamConsole.msg "%s\n" (OpamRepositoryName.to_string r))
rt.repositories
else
let repos_switches, _ =
let repos = OpamGlobalState.repos_list rt.repos_global in
let n_repos = List.length repos in
List.fold_left (fun (acc,i) repo ->
OpamRepositoryName.Map.add repo [None, (i, n_repos)] acc,
i + 1)
(OpamRepositoryName.Map.empty, 1)
repos
in
let repos_switches =
List.fold_left (fun acc sw ->
let repos = switch_repos rt sw in
let n_repos = List.length repos in
let acc,_ =
List.fold_left (fun (acc,i) repo ->
OpamRepositoryName.Map.update repo
(fun s -> (Some sw, (i, n_repos))::s) [] acc,
i + 1)
(acc,1) repos
in acc)
repos_switches
(OpamFile.Config.installed_switches rt.repos_global.config)
in
let cols =
List.map (OpamConsole.colorise `blue)
["# Repository"; "# Url"; "# Switches(rank)"]
in
let lines =
OpamRepositoryName.Map.mapi (fun name repo -> [
OpamRepositoryName.to_string name |> OpamConsole.colorise `bold;
OpamUrl.to_string repo.repo_url;
OpamStd.List.concat_map " "
(fun (sw,(i, n)) ->
OpamStd.Option.to_string ~none:"<default>"
OpamSwitch.to_string sw ^
(if n = 1 then "" else
Printf.sprintf "(%d/%d)" i n |> OpamConsole.colorise `yellow))
(List.rev (try OpamRepositoryName.Map.find name repos_switches
with Not_found -> []));
])
rt.repositories
in
cols :: OpamRepositoryName.Map.values lines |>
OpamStd.Format.align_table |>
OpamConsole.print_table stdout ~sep:" "
let update_with_auto_upgrade rt repo_names =
let repos = List.map (OpamRepositoryState.get_repo rt) repo_names in
let failed, rt = OpamUpdate.repositories rt repos in
let failed = List.map (fun r -> r.repo_name) failed in
if OpamFormatConfig.(!r.skip_version_checks) ||
OpamClientConfig.(!r.no_auto_upgrade)
then
failed, rt
else
let rt, done_upgrade =
List.fold_left (fun (rt, done_upgrade) r ->
if List.mem r.repo_name failed then rt, done_upgrade else
let def =
OpamRepositoryName.Map.find r.repo_name rt.repos_definitions
in
let need_upgrade = match OpamFile.Repo.opam_version def with
| None ->
OpamConsole.note
"Repository at %s doesn't define its version, assuming it's 1.2."
(OpamUrl.to_string r.repo_url);
true
| Some v when
OpamVersion.compare v OpamAdminRepoUpgrade.upgradeto_version < 0
-> true
| _ -> false
in
if need_upgrade then
(if not done_upgrade then
(OpamConsole.header_msg
"Upgrading repositories from older opam format";
OpamRepositoryState.Cache.remove ());
OpamConsole.msg "Upgrading repository \"%s\"...\n"
(OpamRepositoryName.to_string r.repo_name);
let open OpamProcess.Job.Op in
let repo_root = OpamRepositoryState.get_repo_root rt r in
OpamAdminRepoUpgrade.do_upgrade repo_root;
if OpamRepositoryConfig.(!r.repo_tarring) then
OpamProcess.Job.run
(OpamFilename.make_tar_gz_job
(OpamRepositoryPath.tar rt.repos_global.root r.repo_name)
repo_root
@@| function
| Some e ->
Printf.ksprintf failwith
"Failed to regenerate local repository archive: %s"
(Printexc.to_string e)
| None -> ());
let def =
OpamFile.Repo.safe_read (OpamRepositoryPath.repo repo_root) |>
OpamFile.Repo.with_root_url r.repo_url
in
let opams =
OpamRepositoryState.load_opams_from_dir r.repo_name repo_root
in
let rt = {
rt with
repos_definitions =
OpamRepositoryName.Map.add r.repo_name def rt.repos_definitions;
repo_opams =
OpamRepositoryName.Map.add r.repo_name opams rt.repo_opams;
} in
rt, true)
else rt, done_upgrade)
(rt, false) repos
in
if done_upgrade then OpamRepositoryState.Cache.save rt;
failed, rt