54 lines
1.7 KiB
OCaml
54 lines
1.7 KiB
OCaml
type t = { path : string; keys : (string, string) Hashtbl.t }
|
|
|
|
let load path =
|
|
let keys = Hashtbl.create 64 in
|
|
(match Fs.read path with
|
|
| exception Sys_error _ -> ()
|
|
| raw ->
|
|
String.split_on_char '\n' raw
|
|
|> List.iter (fun line ->
|
|
match String.index_opt line '\t' with
|
|
| None -> ()
|
|
| Some i ->
|
|
let key = String.sub line 0 i in
|
|
let out = String.sub line (i + 1) (String.length line - i - 1) in
|
|
if out <> "" then Hashtbl.replace keys out key));
|
|
{ path; keys }
|
|
|
|
let save c =
|
|
let b = Buffer.create 4096 in
|
|
Hashtbl.iter (fun out key -> Buffer.add_string b (key ^ "\t" ^ out ^ "\n")) c.keys;
|
|
Fs.write c.path (Buffer.contents b)
|
|
|
|
let current c out = Hashtbl.find_opt c.keys out
|
|
let put c out key = Hashtbl.replace c.keys out key
|
|
let drop c out = Hashtbl.remove c.keys out
|
|
|
|
let digests : (string, string option) Hashtbl.t = Hashtbl.create 256
|
|
|
|
let digest_file p =
|
|
match Hashtbl.find_opt digests p with
|
|
| Some d -> d
|
|
| None ->
|
|
let d = match Digest.file p with d -> Some (Digest.to_hex d) | exception Sys_error _ -> None in
|
|
Hashtbl.replace digests p d;
|
|
d
|
|
|
|
let forget p = Hashtbl.remove digests p
|
|
|
|
(* The memo saves re-hashing a header that half the project includes, so it is
|
|
only ever valid for one build. A watch loop runs many in one process. *)
|
|
let reset () = Hashtbl.reset digests
|
|
|
|
let key ~cmd ~inputs =
|
|
let b = Buffer.create 256 in
|
|
Buffer.add_string b cmd;
|
|
List.iter
|
|
(fun p ->
|
|
Buffer.add_char b '\000';
|
|
Buffer.add_string b p;
|
|
Buffer.add_char b '\000';
|
|
Buffer.add_string b (match digest_file p with Some d -> d | None -> "?"))
|
|
(List.sort compare inputs);
|
|
Digest.to_hex (Digest.string (Buffer.contents b))
|