Digests every input plus the exact argument vector into one key, persisted under the build directory. Staleness becomes a content question rather than a timestamp comparison.
40 lines
1.3 KiB
OCaml
40 lines
1.3 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 digest_file p = match Digest.file p with d -> Some (Digest.to_hex d) | exception Sys_error _ -> None
|
|
|
|
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))
|