Commit f377ea1060

mlugg <mlugg@mlugg.co.uk>
2025-05-15 22:43:52
doctest: handle relative paths correctly
Evaluate all child processes in the temporary directory, and use `std.fs.path.relative` to make every other path relative to that child cwd instead of our cwd. Resolves: #22119
1 parent 455ea58
Changed files (1)
tools/doctest.zig
@@ -89,7 +89,18 @@ pub fn main() !void {
     const out = bw.writer();
 
     try printSourceBlock(arena, out, source, fs.path.basename(input_path));
-    try printOutput(arena, out, code, input_path, zig_path, opt_zig_lib_dir, tmp_dir_path);
+    try printOutput(
+        arena,
+        out,
+        code,
+        tmp_dir_path,
+        try std.fs.path.relative(arena, tmp_dir_path, zig_path),
+        try std.fs.path.relative(arena, tmp_dir_path, input_path),
+        if (opt_zig_lib_dir) |zig_lib_dir|
+            try std.fs.path.relative(arena, tmp_dir_path, zig_lib_dir)
+        else
+            null,
+    );
 
     try bw.flush();
 }
@@ -98,10 +109,14 @@ fn printOutput(
     arena: Allocator,
     out: anytype,
     code: Code,
-    input_path: []const u8,
+    /// Relative to this process' cwd.
+    tmp_dir_path: []const u8,
+    /// Relative to `tmp_dir_path`.
     zig_exe: []const u8,
+    /// Relative to `tmp_dir_path`.
+    input_path: []const u8,
+    /// Relative to `tmp_dir_path`.
     opt_zig_lib_dir: ?[]const u8,
-    tmp_dir_path: []const u8,
 ) !void {
     var env_map = try process.getEnvMap(arena);
     try env_map.put("CLICOLOR_FORCE", "1");
@@ -304,7 +319,7 @@ fn printOutput(
                     },
                 }
             }
-            const result = run(arena, &env_map, null, test_args.items) catch
+            const result = run(arena, &env_map, tmp_dir_path, test_args.items) catch
                 fatal("test failed", .{});
             const escaped_stderr = try escapeHtml(arena, result.stderr);
             const escaped_stdout = try escapeHtml(arena, result.stdout);
@@ -339,6 +354,7 @@ fn printOutput(
                 .allocator = arena,
                 .argv = test_args.items,
                 .env_map = &env_map,
+                .cwd = tmp_dir_path,
                 .max_output_bytes = max_doc_file_size,
             });
             switch (result.term) {
@@ -395,6 +411,7 @@ fn printOutput(
                 .allocator = arena,
                 .argv = test_args.items,
                 .env_map = &env_map,
+                .cwd = tmp_dir_path,
                 .max_output_bytes = max_doc_file_size,
             });
             switch (result.term) {
@@ -432,10 +449,7 @@ fn printOutput(
                 zig_exe,    "build-obj",
                 "--color",  "on",
                 "--name",   code_name,
-                input_path,
-                try std.fmt.allocPrint(arena, "-femit-bin={s}{c}{s}", .{
-                    tmp_dir_path, fs.path.sep, name_plus_obj_ext,
-                }),
+                input_path, try std.fmt.allocPrint(arena, "-femit-bin={s}", .{name_plus_obj_ext}),
             });
             if (opt_zig_lib_dir) |zig_lib_dir| {
                 try build_args.appendSlice(&.{ "--zig-lib-dir", zig_lib_dir });
@@ -465,6 +479,7 @@ fn printOutput(
                     .allocator = arena,
                     .argv = build_args.items,
                     .env_map = &env_map,
+                    .cwd = tmp_dir_path,
                     .max_output_bytes = max_doc_file_size,
                 });
                 switch (result.term) {
@@ -489,7 +504,7 @@ fn printOutput(
                 const colored_stderr = try termColor(arena, escaped_stderr);
                 try shell_out.print("\n{s} ", .{colored_stderr});
             } else {
-                _ = run(arena, &env_map, null, build_args.items) catch fatal("example failed to compile", .{});
+                _ = run(arena, &env_map, tmp_dir_path, build_args.items) catch fatal("example failed to compile", .{});
             }
             try shell_out.writeAll("\n");
         },
@@ -505,10 +520,7 @@ fn printOutput(
 
             try test_args.appendSlice(&[_][]const u8{
                 zig_exe,    "build-lib",
-                input_path,
-                try std.fmt.allocPrint(arena, "-femit-bin={s}{s}{s}", .{
-                    tmp_dir_path, fs.path.sep_str, bin_basename,
-                }),
+                input_path, try std.fmt.allocPrint(arena, "-femit-bin={s}", .{bin_basename}),
             });
             if (opt_zig_lib_dir) |zig_lib_dir| {
                 try test_args.appendSlice(&.{ "--zig-lib-dir", zig_lib_dir });
@@ -542,7 +554,7 @@ fn printOutput(
                 try test_args.append(option);
                 try shell_out.print("{s} ", .{option});
             }
-            const result = run(arena, &env_map, null, test_args.items) catch fatal("test failed", .{});
+            const result = run(arena, &env_map, tmp_dir_path, test_args.items) catch fatal("test failed", .{});
             const escaped_stderr = try escapeHtml(arena, result.stderr);
             const escaped_stdout = try escapeHtml(arena, result.stdout);
             try shell_out.print("\n{s}{s}\n", .{ escaped_stderr, escaped_stdout });
@@ -1076,7 +1088,7 @@ fn in(slice: []const u8, number: u8) bool {
 fn run(
     allocator: Allocator,
     env_map: *process.EnvMap,
-    cwd: ?[]const u8,
+    cwd: []const u8,
     args: []const []const u8,
 ) !process.Child.RunResult {
     const result = try process.Child.run(.{