Skip to content

Commit ee9ea62

Browse files
committed
fix(cram): build-path-prefix-map substitutions
Signed-off-by: ArthurW <[email protected]>
1 parent 5033aa6 commit ee9ea62

File tree

10 files changed

+216
-48
lines changed

10 files changed

+216
-48
lines changed

doc/changes/11366.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Fix cram tests build-path-prefix-map substitutions (#11366, @art-w)

doc/tests.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -690,9 +690,9 @@ the standard BUILD_PATH_PREFIX_MAP_ environment variable. For example:
690690

691691
.. code:: console
692692
693-
$ export BUILD_PATH_PREFIX_MAP="HOME=$HOME:$BUILD_PATH_PREFIX_MAP"
693+
$ export BUILD_PATH_PREFIX_MAP="/HOME=$HOME:$BUILD_PATH_PREFIX_MAP"
694694
$ echo $HOME
695-
$HOME
695+
/HOME
696696
697697
Note: Unlike Dune's version of Cram, the original specification for Cram
698698
supports regular expression and glob filtering for matching output. We chose

src/dune_engine/process.ml

+40-10
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,14 @@ let report_process_finished
855855

856856
let set_temp_dir_when_running_actions = ref true
857857

858+
let set_temp_dir ~temp_dir env =
859+
match temp_dir, !set_temp_dir_when_running_actions with
860+
| Some path, _ ->
861+
Env.add env ~var:Env.Var.temp_dir ~value:(Path.to_absolute_filename path)
862+
| None, true -> Dtemp.add_to_env env
863+
| None, false -> env
864+
;;
865+
858866
let await { response_file; pid; _ } =
859867
let+ process_info, termination_reason =
860868
Scheduler.wait_for_build_process pid ~is_process_group_leader:true
@@ -865,6 +873,7 @@ let await { response_file; pid; _ } =
865873

866874
let spawn
867875
?dir
876+
?temp_dir
868877
?(env = Env.initial)
869878
~(stdout : _ Io.t)
870879
~(stderr : _ Io.t)
@@ -933,14 +942,7 @@ let spawn
933942
Unix.gettimeofday ()
934943
in
935944
let pid =
936-
let env =
937-
let env =
938-
match !set_temp_dir_when_running_actions with
939-
| true -> Dtemp.add_to_env env
940-
| false -> env
941-
in
942-
Env.to_unix env |> Spawn.Env.of_list
943-
in
945+
let env = set_temp_dir ~temp_dir env |> Env.to_unix |> Spawn.Env.of_list in
944946
let stdout = Io.fd stdout in
945947
let stderr = Io.fd stderr in
946948
let stdin = Io.fd stdin in
@@ -976,6 +978,7 @@ let spawn
976978

977979
let run_internal
978980
?dir
981+
?temp_dir
979982
~(display : Display.t)
980983
?(stdout_to = Io.stdout)
981984
?(stderr_to = Io.stderr)
@@ -1015,7 +1018,16 @@ let run_internal
10151018
| _ -> Pp.nop
10161019
in
10171020
let t =
1018-
spawn ?dir ?env ~stdout:stdout_to ~stderr:stderr_to ~stdin:stdin_from ~prog ~args ()
1021+
spawn
1022+
?dir
1023+
?temp_dir
1024+
?env
1025+
~stdout:stdout_to
1026+
~stderr:stderr_to
1027+
~stdin:stdin_from
1028+
~prog
1029+
~args
1030+
()
10191031
in
10201032
let* () =
10211033
let description =
@@ -1092,11 +1104,23 @@ let run_internal
10921104
res, times)
10931105
;;
10941106

1095-
let run ?dir ~display ?stdout_to ?stderr_to ?stdin_from ?env ?metadata fail_mode prog args
1107+
let run
1108+
?dir
1109+
?temp_dir
1110+
~display
1111+
?stdout_to
1112+
?stderr_to
1113+
?stdin_from
1114+
?env
1115+
?metadata
1116+
fail_mode
1117+
prog
1118+
args
10961119
=
10971120
let+ run =
10981121
run_internal
10991122
?dir
1123+
?temp_dir
11001124
~display
11011125
?stdout_to
11021126
?stderr_to
@@ -1113,6 +1137,7 @@ let run ?dir ~display ?stdout_to ?stderr_to ?stdin_from ?env ?metadata fail_mode
11131137

11141138
let run_with_times
11151139
?dir
1140+
?temp_dir
11161141
~display
11171142
?stdout_to
11181143
?stderr_to
@@ -1126,6 +1151,7 @@ let run_with_times
11261151
let+ code, times =
11271152
run_internal
11281153
?dir
1154+
?temp_dir
11291155
~display
11301156
?stdout_to
11311157
?stderr_to
@@ -1141,6 +1167,7 @@ let run_with_times
11411167

11421168
let run_capture_gen
11431169
?dir
1170+
?temp_dir
11441171
~display
11451172
?stderr_to
11461173
?stdin_from
@@ -1155,6 +1182,7 @@ let run_capture_gen
11551182
let+ run =
11561183
run_internal
11571184
?dir
1185+
?temp_dir
11581186
~display
11591187
~stdout_to:(Io.file fn Io.Out)
11601188
?stderr_to
@@ -1178,6 +1206,7 @@ let run_capture_zero_separated = run_capture_gen ~f:Stdune.Io.zero_strings_of_fi
11781206

11791207
let run_capture_line
11801208
?dir
1209+
?temp_dir
11811210
~display
11821211
?stderr_to
11831212
?stdin_from
@@ -1189,6 +1218,7 @@ let run_capture_line
11891218
=
11901219
run_capture_gen
11911220
?dir
1221+
?temp_dir
11921222
~display
11931223
?stderr_to
11941224
?stdin_from

src/dune_engine/process.mli

+6
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ val set_temp_dir_when_running_actions : bool ref
9090
termination. [stdout_to] [stderr_to] are released *)
9191
val run
9292
: ?dir:Path.t
93+
-> ?temp_dir:Path.t
9394
-> display:Display.t
9495
-> ?stdout_to:Io.output Io.t
9596
-> ?stderr_to:Io.output Io.t
@@ -103,6 +104,7 @@ val run
103104

104105
val run_with_times
105106
: ?dir:Path.t
107+
-> ?temp_dir:Path.t
106108
-> display:Display.t
107109
-> ?stdout_to:Io.output Io.t
108110
-> ?stderr_to:Io.output Io.t
@@ -117,6 +119,7 @@ val run_with_times
117119
(** Run a command and capture its output *)
118120
val run_capture
119121
: ?dir:Path.t
122+
-> ?temp_dir:Path.t
120123
-> display:Display.t
121124
-> ?stderr_to:Io.output Io.t
122125
-> ?stdin_from:Io.input Io.t
@@ -129,6 +132,7 @@ val run_capture
129132

130133
val run_capture_line
131134
: ?dir:Path.t
135+
-> ?temp_dir:Path.t
132136
-> display:Display.t
133137
-> ?stderr_to:Io.output Io.t
134138
-> ?stdin_from:Io.input Io.t
@@ -141,6 +145,7 @@ val run_capture_line
141145

142146
val run_capture_lines
143147
: ?dir:Path.t
148+
-> ?temp_dir:Path.t
144149
-> display:Display.t
145150
-> ?stderr_to:Io.output Io.t
146151
-> ?stdin_from:Io.input Io.t
@@ -153,6 +158,7 @@ val run_capture_lines
153158

154159
val run_capture_zero_separated
155160
: ?dir:Path.t
161+
-> ?temp_dir:Path.t
156162
-> display:Display.t
157163
-> ?stderr_to:Io.output Io.t
158164
-> ?stdin_from:Io.input Io.t

src/dune_rules/action_unexpanded.ml

+9-2
Original file line numberDiff line numberDiff line change
@@ -564,8 +564,15 @@ let rec expand (t : Dune_lang.Action.t) : Action.t Action_expander.t =
564564
let+ l = A.all (List.map l ~f:expand) in
565565
O.Pipe (outputs, l)
566566
| Cram script ->
567-
let+ script = E.dep script in
568-
Cram_exec.action script
567+
A.with_expander (fun expander ->
568+
let open Memo.O in
569+
let+ version =
570+
let dir = Expander.dir expander in
571+
Dune_load.find_project ~dir >>| Dune_project.dune_version
572+
in
573+
let open Action_expander.O in
574+
let+ script = E.dep script in
575+
Cram_exec.action ~version script)
569576
| Format_dune_file (src, dst) ->
570577
A.with_expander (fun expander ->
571578
let open Memo.O in

src/dune_rules/cram/cram_exec.ml

+48-27
Original file line numberDiff line numberDiff line change
@@ -259,17 +259,31 @@ let line_number =
259259
seq [ set "123456789"; rep digit ]
260260
;;
261261

262-
let rewrite_paths build_path_prefix_map ~parent_script ~command_script s =
262+
let absolute_paths =
263+
let not_dir = Printf.sprintf " \n\r\t%c" Bin.path_sep in
264+
Re.(compile (seq [ char '/'; rep1 (diff any (set not_dir)) ]))
265+
;;
266+
267+
let known_paths map =
268+
List.filter_map
269+
~f:(function
270+
| None | Some { Build_path_prefix_map.source = ""; _ } -> None
271+
| Some pair -> Some (Re.str pair.source))
272+
map
273+
|> List.rev
274+
(* prefer right-most paths in the list, as required by the build-path-prefix-map spec *)
275+
|> Re.alt
276+
|> Re.compile
277+
;;
278+
279+
let rewrite_paths ~version ~build_path_prefix_map ~parent_script ~command_script s =
263280
match Build_path_prefix_map.decode_map build_path_prefix_map with
264281
| Error msg ->
265282
Code_error.raise
266283
"Cannot decode build prefix map"
267284
[ "build_path_prefix_map", String build_path_prefix_map; "msg", String msg ]
268285
| Ok map ->
269-
let abs_path_re =
270-
let not_dir = Printf.sprintf " \n\r\t%c" Bin.path_sep in
271-
Re.(compile (seq [ char '/'; rep1 (diff any (set not_dir)) ]))
272-
in
286+
let known_paths = if version < (3, 18) then absolute_paths else known_paths map in
273287
let error_msg =
274288
let open Re in
275289
let command_script = str (Path.to_absolute_filename command_script) in
@@ -281,12 +295,12 @@ let rewrite_paths build_path_prefix_map ~parent_script ~command_script s =
281295
let b = seq [ command_script; str ": line "; line_number; str ": " ] in
282296
[ a; b ] |> List.map ~f:(fun re -> seq [ bol; re ]) |> alt |> compile
283297
in
284-
Re.replace abs_path_re s ~f:(fun g ->
298+
Re.replace ~all:true known_paths s ~f:(fun g ->
285299
Build_path_prefix_map.rewrite map (Re.Group.get g 0))
286300
|> Re.replace_string error_msg ~by:""
287301
;;
288302

289-
let sanitize ~parent_script cram_to_output
303+
let sanitize ~version ~parent_script cram_to_output
290304
: (block_result * metadata_result * string) Cram_lexer.block list
291305
=
292306
List.map cram_to_output ~f:(fun (t : (block_result * _) Cram_lexer.block) ->
@@ -300,9 +314,10 @@ let sanitize ~parent_script cram_to_output
300314
Io.read_file ~binary:false block_result.output_file
301315
|> Ansi_color.strip
302316
|> rewrite_paths
317+
~version
303318
~parent_script
304319
~command_script:block_result.script
305-
build_path_prefix_map
320+
~build_path_prefix_map
306321
in
307322
Command (block_result, metadata, output))
308323
;;
@@ -389,7 +404,7 @@ let create_sh_script cram_stanzas ~temp_dir : sh_script Fiber.t =
389404

390405
let _display_with_bars s = List.iter (String.split_lines s) ~f:(Printf.eprintf "| %s\n")
391406

392-
let run ~env ~script lexbuf : string Fiber.t =
407+
let run ~version ~env ~script lexbuf : string Fiber.t =
393408
let temp_dir =
394409
let suffix =
395410
let basename = Path.basename script in
@@ -406,19 +421,16 @@ let run ~env ~script lexbuf : string Fiber.t =
406421
let open Fiber.O in
407422
let* sh_script = create_sh_script cram_stanzas ~temp_dir in
408423
let cwd = Path.parent_exn script in
424+
let temp_dir = Path.relative temp_dir "tmp" in
425+
Path.mkdir_p temp_dir;
409426
let env =
410427
let env = Env.add env ~var:"LC_ALL" ~value:"C" in
411-
let temp_dir = Path.relative temp_dir "tmp" in
412-
let env =
413-
Dune_util.Build_path_prefix_map.extend_build_path_prefix_map
414-
env
415-
`New_rules_have_precedence
416-
[ Some { source = Path.to_absolute_filename cwd; target = "$TESTCASE_ROOT" }
417-
; Some { source = Path.to_absolute_filename temp_dir; target = "$TMPDIR" }
418-
]
419-
in
420-
Path.mkdir_p temp_dir;
421-
Env.add env ~var:Env.Var.temp_dir ~value:(Path.to_absolute_filename temp_dir)
428+
Dune_util.Build_path_prefix_map.extend_build_path_prefix_map
429+
env
430+
`New_rules_have_precedence
431+
[ Some { source = Path.to_absolute_filename cwd; target = "$TESTCASE_ROOT" }
432+
; Some { source = Path.to_absolute_filename temp_dir; target = "$TMPDIR" }
433+
]
422434
in
423435
let open Fiber.O in
424436
let+ () =
@@ -442,29 +454,38 @@ let run ~env ~script lexbuf : string Fiber.t =
442454
~display:Quiet
443455
~metadata
444456
~dir:cwd
457+
~temp_dir
445458
~env
446459
Strict
447460
sh
448461
[ Path.to_string sh_script.script ]
449462
in
450463
let raw = read_and_attach_exit_codes sh_script in
451-
let sanitized = sanitize ~parent_script:sh_script.script raw in
464+
let sanitized = sanitize ~version ~parent_script:sh_script.script raw in
452465
compose_cram_output sanitized
453466
;;
454467

455-
let run ~env ~script = run_expect_test script ~f:(fun lexbuf -> run ~env ~script lexbuf)
468+
let run ~version ~env ~script =
469+
run_expect_test script ~f:(fun lexbuf -> run ~version ~env ~script lexbuf)
470+
;;
456471

457472
module Spec = struct
458-
type ('path, _) t = 'path
473+
type ('path, _) t = Dune_lang.Syntax.Version.t * 'path
459474

460475
let name = "cram"
461476
let version = 2
462-
let bimap path f _ = f path
477+
let bimap (version, path) f _ = version, f path
463478
let is_useful_to ~memoize:_ = true
464-
let encode script path _ : Sexp.t = List [ path script ]
465-
let action script ~ectx:_ ~(eenv : Action.env) = run ~env:eenv.env ~script
479+
480+
let encode (version, script) path _ : Sexp.t =
481+
List [ Dune_lang.Syntax.Version.encode version |> Dune_sexp.to_sexp; path script ]
482+
;;
483+
484+
let action (version, script) ~ectx:_ ~(eenv : Action.env) =
485+
run ~version ~env:eenv.env ~script
486+
;;
466487
end
467488

468489
module Action = Action_ext.Make (Spec)
469490

470-
let action = Action.action
491+
let action ~version path = Action.action (version, path)

src/dune_rules/cram/cram_exec.mli

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
open Import
22

3-
val action : Path.t -> Action.t
3+
val action : version:Dune_lang.Syntax.Version.t -> Path.t -> Action.t

0 commit comments

Comments
 (0)