open Common type subsystem_info = subsystem list and subsystem = Subsystem of (dir * maintainers) * (dir * maintainers) list (* subdirs *) and dir = string and maintainers = string list let mk_inverted_index_subsystem xs = let h = Hashtbl.create 101 in xs +> List.iter (function (Subsystem ((leader, emails), dirs)) -> Hashtbl.add h leader leader; dirs +> List.iter (fun (subdir, emails) -> Hashtbl.add h subdir leader )); h let subsystem_to_assoc xs = xs +> List.map (function (Subsystem ((s, emails), ys)) -> s, (emails, ys)) let subsystem_to_hash xs = xs +> subsystem_to_assoc +> Common.hash_of_list let all_dirs_from_subsystem_info xs = xs +> List.map (function (Subsystem ((s, emails), dirs)) -> s::(List.map fst dirs) ) +> Common.union_all let unparse_subsystem_info xs filename = Common.with_open_outfile filename (fun (pr_no_nl,chan) -> let pr s = pr_no_nl (s ^ "\n") in xs +> List.iter (function Subsystem ((s, emails), ys) -> pr (sprintf "%-40s : %s" s (Common.join " ," emails)); ys +> List.iter (fun (s, emails) -> pr (sprintf " %-40s : %s" s (Common.join " ," emails)); ); pr ""; ) ) let parse_subsystem_info filename = let xs = cat filename in let xs = xs +> List.map (Str.global_replace (Str.regexp "#.*") "" ) in let xs = xs +> List.filter (fun s -> not (s =~ "^[ \t]*$")) in (* split by header of section *) let xs = xs +> Common.split_list_regexp "^[^ ]" in xs +> List.map (fun (s, xs) -> assert (s =~ "^\\([^ ]+\\) *: *\\(.*\\)"); let (dir, email) = matched2 s in let emails = Common.split "[ ,]+" email in let group = xs +> List.map (fun s -> assert (s =~ "^[ ]+\\([^ ]+\\) *: *\\(.*\\)"); let (dir, email) = matched2 s in let emails = Common.split "[ ,]+" email in (dir, emails) ) in Subsystem ((dir, emails), group) ) let generate_naive_subsystem_info dirs = let dirs' = dirs +> List.map (fun s -> Common.split "/" s, s ) in let rec aux_dirs xs = match xs with | [] -> [] | (dir_elems,s)::xs -> let cond, base = if List.length dir_elems >= 2 then let base = Common.take 2 dir_elems in (fun dir_elems' -> List.length dir_elems' >= 2 && Common.take 2 dir_elems' =*= base), base else (fun dir_elems' -> dir_elems' =*= dir_elems), dir_elems in let (yes, no) = xs +> Common.partition_either (fun (dir_elems', x) -> if cond dir_elems' then Left (x, []) else Right (dir_elems', x) ) in (Subsystem ((s, [""]), yes))::aux_dirs no in aux_dirs dirs' (* old: dirs +> List.map (fun s -> Subsystem (s, "", [])) *) (* a = current info file, in general manually extended; b = generated one *) let check_up_to_date a b = let set1 = all_dirs_from_subsystem_info a in let set2 = all_dirs_from_subsystem_info b in (set1 $-$ set2) +> List.iter (fun s -> pr2 ("old directory disappeared: " ^ s) ); (set2 $-$ set1) +> List.iter (fun s -> pr2 ("new directory appeared: " ^ s) )