/
config.ml
128 lines (114 loc) · 3.64 KB
/
config.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
open Common
open Types
let read_all_lines ch =
Filew.channel_lines ch
let parse_line_opt s =
if String.length s > 0 then
some &
Scanf.sscanf s " dep %s %s %s " (fun name typ src ->
(* FIXME(superbobry): doesn't cover the new type schema! *)
let package = match String.lowercase typ with
| "remote" ->
let ends = String.ends_with src in
if ends ".tar.gz" then Remote (`TarGz, src)
else if ends ".tar.bz2" then Remote (`TarBzip2, src)
else if ends ".tar" then Remote (`Tar, src)
else Log.error "can't guess remote archive format: %S\n" typ
| "remote-tar-gz" -> Remote (`TarGz, src)
| "remote-tar-bz2" -> Remote (`TarBzip2, src)
| "remote-tar" -> Remote (`Tar, src)
| "local-tar-gz" -> Local (`TarGz, src)
| "local-tar-bz2" -> Local (`TarBzip2, src)
| "local-tar" -> Local (`Tar, src)
| "local-dir" -> Local (`Directory, src)
| "bundled-dir" -> Bundled (`Directory, src)
| "bundled-tar" -> Bundled (`Tar, src)
| "bundled-tar-gz" -> Bundled (`TarGz, src)
| "bundled-tar-bz2" -> Bundled (`TarBzip2, src)
| "svn" | "csv" | "hg" | "git" | "bzr" | "darcs" ->
VCS (vcs_type_of_string typ, src)
| _ -> Log.error "unsupported package type: %S when source = %S\n" typ src
in (name, package)
)
else
None
let stream_filter : 'a . ('a -> bool) -> 'a Stream.t -> 'a Stream.t
= fun pred s ->
(* todo: implement directly *)
Stream.map_filter (fun x -> if pred x then Some x else None) s
let line_means_something line =
let len = String.length line in
let rec inner i =
if i = len
then false
else
begin match line.[i] with
'#' -> false
| '\x20' | '\x09' | '\x0A' | '\x0D' -> inner (i + 1)
| _ -> true
end
in
inner 0
let filter_comments s =
stream_filter line_means_something s
let check_dupes_v1 : db -> unit = fun db ->
let sorted = List.sort
(fun (n1, _p1) (n2, _p2) -> String.compare n1 n2) db in
begin match sorted with
| [] -> ()
| (hn, _hp) :: t ->
let rec loop hn t =
begin match t with
| [] -> ()
| (hn', _hp') :: t' ->
if hn = hn'
then Log.error "brb.conf: duplicate dependency %S" hn
else loop hn' t'
end
in loop hn t
end
let parse_config_v1 s =
s
(* |> Stream.map (fun line -> let () = dbg "line: %s" line in line) *)
|> Stream.map_filter parse_line_opt
|> Stream.to_list
|> fun r -> begin
check_dupes_v1 r;
r
end
let remove_CR s =
Stream.map
(fun line ->
let len = String.length line in
if len > 0 && line.[len - 1] = '\x0D'
then String.sub line 0 (len - 1)
else line
)
s
let get_config_version s =
begin match Stream.next_opt s with
None -> Log.error "brb.conf empty!"
| Some line ->
try
(* let () = dbg "get_config_version: line = %S" line in *)
Scanf.sscanf (String.lowercase line) " version %s "
(fun v -> v)
with Scanf.Scan_failure _ ->
Log.error "brb.conf: missing version!"
end
let parse_stream s =
s
|> remove_CR
|> filter_comments
|> fun s ->
begin match get_config_version s with
| "1" -> parse_config_v1 s
| v -> Log.error "brb.conf: unknown version %S" v
end
let parse_config filename =
filename
|> Filew.stream_of_file_lines
|> parse_stream
let parse_string st =
let lines = String.nsplit st "\n" in
parse_stream (Stream.of_list lines)