-
Notifications
You must be signed in to change notification settings - Fork 0
/
pkgdb.ml
180 lines (167 loc) · 4.8 KB
/
pkgdb.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
open Pkg
open Hashtbl
open Util
type pkgdb = (string, static_pkg list) Hashtbl.t
let create_empty () : pkgdb =
Hashtbl.create ~random:true 1000
let add_spkg (db : pkgdb) (spkg : static_pkg) =
let l =
match Hashtbl.find_opt db spkg.sn with
| None -> []
| Some l -> l
in
Hashtbl.replace db spkg.sn (spkg::l)
let read (filepath : string) =
let process_element (db : pkgdb) e =
match pkg_of_xml e with
| None ->
failwith "pkg_of_xml failed"
| Some pkg ->
match static_of_dynamic_pkg pkg with
| None ->
failwith "static_of_dynamic_pkg failed"
| Some spkg ->
add_spkg db spkg
in
let process_elements es =
let db = create_empty ()
in
List.fold_left
(fun () e -> process_element db e)
()
es;
db
in
try
let x =
Xml.parse_file filepath
in
match x with
| Xml.PCData _ ->
failwith "Data on toplevel, which is invalid"
| Xml.Element ("pkgdb", attrs, children) ->
(match List.assoc_opt "file_version" attrs with
| None ->
failwith "File_version attribute is missing"
| Some v when v = Tpm_config.desc_file_version ->
Some (process_elements children)
| Some v ->
failwith ("Invalid db file version \"" ^ v ^ "\""))
| Xml.Element (n, _, _) ->
failwith ("Invalid toplevel element \"" ^ n ^ "\"")
with
| Failure msg
| Sys_error msg ->
print_endline ("Pkgdb.read: " ^ msg);
None
| _ ->
print_endline "Pkgdb.read failed";
None
let write (db : pkgdb) (filepath : string) =
try
let xml_pkgs =
Hashtbl.fold
(fun _ spkgs l ->
List.fold_left
(fun l spkg ->
match
(dynamic_of_static_pkg spkg |> xml_of_pkg)
with
| None -> failwith "xml_of_pkg failed"
| Some x -> x :: l)
l
spkgs)
db
[]
in
let attrs =
[ ("file_version", Tpm_config.desc_file_version) ]
in
let x =
Xml.Element ("pkgdb", attrs, xml_pkgs)
in
let oc = open_out filepath
in
xml_to_string_with_desc x |> output_string oc;
close_out oc;
true
with
| Failure msg
| Sys_error msg ->
print_endline ("pkgdb.write: " ^ msg);
false
| _ ->
print_endline ("pkgdb.write failed");
false
(* Varios SQL SELECT-like queries *)
let select_name_version_arch spp fp (db : pkgdb) =
let in_files sp =
let files = sp.sfiles
in
let files =
List.fold_left
(fun l (_, f) -> f::l)
files
sp.scfiles
in
List.exists
fp
files
in
Hashtbl.fold
(fun n sps o ->
List.filter
(fun sp ->
if spp sp
then in_files sp
else false)
sps @ o)
db
[]
|> List.map (fun sp -> (sp.sn, sp.sv, sp.sa))
let select_name_version_arch_in_latest_version spp fp (db : pkgdb) =
let in_files sp =
let files = sp.sfiles
in
let files =
List.fold_left
(fun l (_, f) -> f::l)
files
sp.scfiles
in
List.exists
fp
files
in
Hashtbl.fold
(fun n sps o ->
match
list_max
(fun sp1 sp2 -> compare_version sp1.sv sp2.sv)
sps
with
| None -> o
| Some sp ->
if spp sp
then (if in_files sp then sp :: o else o)
else o)
db
[]
|> List.map (fun sp -> (sp.sn, sp.sv, sp.sa))
let select_spkgs spp (db : pkgdb) =
Hashtbl.fold
(fun _ sps l ->
List.filter (fun sp -> if spp sp then true else false) sps @ l)
db
[]
let select_latest_versioned_spkgs spp (db : pkgdb) =
Hashtbl.fold
(fun _ sps l ->
match
list_max (fun sp1 sp2 -> compare_version sp1.sv sp2.sv) sps
with
| None -> l
| Some sp ->
if spp sp then sp :: l else l)
db
[]