Source file conex_repository.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
open Conex_resource
open Conex_utils
type t = {
root : Root.t ;
targets : (Digest.t * Uint.t * S.t) Tree.t ;
}
let root t = t.root
let keydir t = t.root.Root.keydir
let datadir t = t.root.Root.datadir
let maintainer_delegation t =
match M.find "maintainer" t.root.Root.roles with
| None -> None
| Some e -> Some (e, false, S.singleton "root")
let targets t = t.targets
let with_targets t targets = { t with targets }
let create root =
let targets = Tree.empty in
{ root ; targets }
type res = [
| `Only_on_disk of path
| `Only_in_targets of path
| `No_match of path * (Digest.t * Uint.t) list * (Digest.t * Uint.t * S.t) list
]
let pp_res ppf =
let pp_d ppf (dgst, len) =
Format.fprintf ppf "%s bytes, %a" (Uint.decimal len) Digest.pp dgst
and pp_t ppf (dgst, len, _) =
Format.fprintf ppf "%s bytes, %a" (Uint.decimal len) Digest.pp dgst
in
function
| `Only_on_disk p -> Format.fprintf ppf "path %a only exists on disk" pp_path p
| `Only_in_targets p -> Format.fprintf ppf "path %a only exists in targets" pp_path p
| `No_match (p, disk, targets) ->
Format.fprintf ppf "no matching digest for %a (on_disk %a, targets %a)"
pp_path p (pp_list pp_d) disk (pp_list pp_t) targets
let validate_targets t on_disk =
let on_d =
let matches (dgst, len) (dgst', len', _) =
Digest.equal dgst dgst' && Uint.compare len len' = 0
in
Tree.fold (fun path ds acc ->
match ds with
| [] -> acc
| _ -> match Tree.lookup path t.targets with
| None -> `Only_on_disk path :: acc
| Some xs ->
let in_targets d = List.exists (matches d) xs in
if List.exists in_targets ds
then acc
else `No_match (path, ds, xs) :: acc)
[] on_disk
in
Tree.fold (fun path xs acc ->
match xs with
| [] -> acc
| _ -> match Tree.lookup path on_disk with
| None -> `Only_in_targets path :: acc
| Some _ -> acc)
on_d t.targets
let fold_targets f acc id_d targets =
List.fold_left (fun acc target ->
match M.find target.Targets.name id_d with
| None ->
Format.printf "couldn't find id %a in id_d@." pp_id target.Targets.name ;
acc
| Some (dgst, epoch) -> f acc dgst epoch target)
acc targets
module Expr_map = struct
include Map.Make(Expression)
let find k m = try Some (find k m) with Not_found -> None
end
let collect_and_validate_delegations id_d parent expr targets =
let tree =
fold_targets (fun tree dgst epoch target ->
List.fold_left (fun tree delegation ->
List.fold_left (fun tree path ->
if subpath ~parent path then begin
Tree.insert path
(delegation.Delegation.terminating,
delegation.Delegation.valid,
target.Targets.name, dgst, epoch)
tree
end else begin
Format.printf "WARN ignoring delegation %a (path %a is not below parent %a)@."
Delegation.pp delegation
pp_path path pp_path parent ;
tree
end)
tree delegation.Delegation.paths)
tree target.Targets.delegations)
Tree.empty id_d targets
in
let good_ones =
Tree.fold (fun path stuff acc ->
let em =
List.fold_left (fun acc (terminating, expression, id, keyid, epoch) ->
let supporter = (terminating, id, keyid, epoch) in
let v = match Expr_map.find expression acc with
| None -> [ supporter ]
| Some m -> supporter :: m
in
Expr_map.add expression v acc)
Expr_map.empty stuff
in
Expr_map.fold (fun expression ss acc ->
let t, nont = List.partition (fun (t, _, _, _) -> t) ss in
let dms xs =
List.fold_left (fun (dm, s) (_, id, keyid, epoch) ->
Digest_map.add keyid (id, epoch) dm, S.add id s)
(Digest_map.empty, S.empty) xs
in
let ts, tss = dms t
and nonts, nontss = dms nont
in
if Expression.eval expr ts S.empty then
(path, expression, true, tss) :: acc
else if Expression.eval expr nonts S.empty then
(path, expression, false, nontss) :: acc
else begin
Format.printf "expression %a couldn't evaluate for %a@."
Expression.pp expression pp_path path ;
acc
end) em acc)
[] tree
in
good_ones
let collect_and_validate_targets ?(tree = Tree.empty) id_d parent expr targets =
let ttree =
fold_targets (fun tree dgst epoch target ->
List.fold_left (fun tree chk ->
if subpath ~parent chk.Target.filename then begin
Tree.insert chk.Target.filename
(chk.Target.digest, chk.Target.size,
target.Targets.name, dgst, epoch)
tree
end else begin
Format.printf "WARN ignoring target %a (path %a is not below parent %a@."
Target.pp chk pp_path chk.Target.filename pp_path parent ;
tree
end)
tree target.Targets.targets)
Tree.empty id_d targets
in
let good_ones =
Tree.fold (fun path stuff acc ->
let dm =
List.fold_left (fun acc (chks, len, id, keyid, epoch) ->
let supporter = (id, keyid, epoch) in
List.fold_left (fun acc dgst ->
let v = match Digest_map.find dgst acc with
| None -> Uint_map.add len [ supporter ] Uint_map.empty
| Some m ->
match Uint_map.find len m with
| None -> Uint_map.add len [ supporter ] m
| Some sups -> Uint_map.add len (supporter :: sups) m
in
Digest_map.add dgst v acc) acc chks)
Digest_map.empty stuff
in
Digest_map.fold (fun dgst m tree ->
Uint_map.fold (fun len sups tree ->
let dm, s =
List.fold_left (fun (dm, s) (id, keyid, epoch) ->
Digest_map.add keyid (id, epoch) dm, S.add id s)
(Digest_map.empty, S.empty) sups
in
if Expression.eval expr dm S.empty then
Tree.insert path (dgst, len, s) tree
else begin
Format.printf "expression %a couldn't evaluate for %a (digest %a, len %s)@."
Expression.pp expr pp_path path Digest.pp dgst (Uint.decimal len) ;
tree
end) m tree)
dm acc)
tree ttree
in
good_ones