Source file context_cache.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
open Astring
open Action.Syntax
let src = Logs.Src.create "functoria.cache" ~doc:"functoria library"
module Log = (val Logs.src_log src : Logs.LOG)
type t = string array
let empty = [| "" |]
let is_empty t = t = empty
let write file argv =
Log.info (fun m ->
m "Preserving arguments in %a:@ %a" Fpath.pp file
Fmt.Dump.(array string)
argv);
let args = List.tl (Array.to_list argv) in
let args = List.map String.Ascii.escape args in
let args = String.concat ~sep:"\n" args ^ "\n" in
Action.write_file file args
let read file =
Log.info (fun l -> l "reading cache %a" Fpath.pp file);
let* is_file = Action.is_file file in
if not is_file then Action.ok empty
else
let* args = Action.read_file file in
let args = String.cuts ~sep:"\n" args in
let args = List.rev (List.tl (List.rev args)) in
let args = "" :: args in
let args = Array.of_list args in
try
let args =
Array.map
(fun x ->
match String.Ascii.unescape x with
| Some s -> s
| None -> Fmt.failwith "%S: cannot parse" x)
args
in
Action.ok args
with Failure e -> Action.error e
let peek t term =
match Cmdliner.Cmd.eval_peek_opts ~argv:t term with
| Some c, _ | _, Ok (`Ok c) -> Some c
| _ -> None
let merge t term =
let cache = match peek t term with None -> Context.empty | Some c -> c in
let f term = Context.merge ~default:cache term in
Cmdliner.Term.(const f $ term)
let peek_output t = Cli.peek_output t
let file ~name args =
let build_dir = Fpath.parent args.Cli.config_file in
match args.Cli.context_file with
| Some f -> f
| None -> Fpath.(build_dir / name / "context")