diff --git a/lib/compiler/std-docs.zig b/lib/compiler/std-docs.zig index 72a8c74ff2..c9ce170051 100644 --- a/lib/compiler/std-docs.zig +++ b/lib/compiler/std-docs.zig @@ -398,7 +398,7 @@ fn buildWasmBinary( if (code != 0) { std.log.err( "the following command exited with error code {d}:\n{s}", - .{ code, try std.Build.Step.allocPrintCmd(arena, null, null, argv.items) }, + .{ code, try std.Build.Step.allocPrintCmd(arena, .inherit, null, argv.items) }, ); return error.WasmCompilationFailed; } @@ -406,14 +406,14 @@ fn buildWasmBinary( .signal => |sig| { std.log.err( "the following command terminated with signal {t}:\n{s}", - .{ sig, try std.Build.Step.allocPrintCmd(arena, null, null, argv.items) }, + .{ sig, try std.Build.Step.allocPrintCmd(arena, .inherit, null, argv.items) }, ); return error.WasmCompilationFailed; }, .stopped, .unknown => { std.log.err( "the following command terminated unexpectedly:\n{s}", - .{try std.Build.Step.allocPrintCmd(arena, null, null, argv.items)}, + .{try std.Build.Step.allocPrintCmd(arena, .inherit, null, argv.items)}, ); return error.WasmCompilationFailed; }, @@ -423,14 +423,14 @@ fn buildWasmBinary( try result_error_bundle.renderToStderr(io, .{}, .auto); std.log.err("the following command failed with {d} compilation errors:\n{s}", .{ result_error_bundle.errorMessageCount(), - try std.Build.Step.allocPrintCmd(arena, null, null, argv.items), + try std.Build.Step.allocPrintCmd(arena, .inherit, null, argv.items), }); return error.WasmCompilationFailed; } return result orelse { std.log.err("child process failed to report result\n{s}", .{ - try std.Build.Step.allocPrintCmd(arena, null, null, argv.items), + try std.Build.Step.allocPrintCmd(arena, .inherit, null, argv.items), }); return error.WasmCompilationFailed; }; diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 242949605c..4517ce75b0 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -1868,7 +1868,7 @@ pub fn runAllowFail( const io = graph.io; const max_output_size = 400 * 1024; - try Step.handleVerbose2(b, null, &graph.environ_map, argv); + try Step.handleVerbose2(b, .inherit, &graph.environ_map, argv); var child = try std.process.spawn(io, .{ .argv = argv, @@ -1911,7 +1911,7 @@ pub fn run(b: *Build, argv: []const []const u8) []u8 { var code: u8 = undefined; return b.runAllowFail(argv, &code, .inherit) catch |err| process.fatal( "the following command failed with {t}:\n{s}", - .{ err, Step.allocPrintCmd(b.allocator, null, null, argv) catch @panic("OOM") }, + .{ err, Step.allocPrintCmd(b.allocator, .inherit, null, argv) catch @panic("OOM") }, ); } diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index cfc263b770..2f5e4316d4 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -350,10 +350,10 @@ pub fn captureChildProcess( // If an error occurs, it's happened in this command: assert(s.result_failed_command == null); - s.result_failed_command = try allocPrintCmd(gpa, null, null, argv); + s.result_failed_command = try allocPrintCmd(gpa, .inherit, null, argv); try handleChildProcUnsupported(s); - try handleVerbose(s.owner, null, argv); + try handleVerbose(s.owner, .inherit, argv); const result = std.process.run(arena, io, .{ .argv = argv, @@ -410,7 +410,7 @@ pub fn evalZigProcess( // If an error occurs, it's happened in this command: assert(s.result_failed_command == null); - s.result_failed_command = try allocPrintCmd(gpa, null, null, argv); + s.result_failed_command = try allocPrintCmd(gpa, .inherit, null, argv); if (s.getZigProcess()) |zp| update: { assert(watch); @@ -449,7 +449,7 @@ pub fn evalZigProcess( assert(argv.len != 0); try handleChildProcUnsupported(s); - try handleVerbose(s.owner, null, argv); + try handleVerbose(s.owner, .inherit, argv); const zp = try gpa.create(ZigProcess); defer if (!watch) gpa.destroy(zp); @@ -515,7 +515,7 @@ pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u const b = s.owner; const io = b.graph.io; const src_path = src_lazy_path.getPath3(b, s); - try handleVerbose(b, null, &.{ "install", "-C", b.fmt("{f}", .{src_path}), dest_path }); + try handleVerbose(b, .inherit, &.{ "install", "-C", b.fmt("{f}", .{src_path}), dest_path }); return Io.Dir.updateFile(src_path.root_dir.handle, io, src_path.sub_path, .cwd(), dest_path, .{}) catch |err| return s.fail("unable to update file from '{f}' to '{s}': {t}", .{ src_path, dest_path, err }); } @@ -524,7 +524,7 @@ pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u pub fn installDir(s: *Step, dest_path: []const u8) !Io.Dir.CreatePathStatus { const b = s.owner; const io = b.graph.io; - try handleVerbose(b, null, &.{ "install", "-d", dest_path }); + try handleVerbose(b, .inherit, &.{ "install", "-d", dest_path }); return Io.Dir.cwd().createDirPathStatus(io, dest_path, .default_dir) catch |err| return s.fail("unable to create dir '{s}': {t}", .{ dest_path, err }); } @@ -700,15 +700,15 @@ fn sendMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag) !void { pub fn handleVerbose( b: *Build, - opt_cwd: ?[]const u8, + cwd: std.process.Child.Cwd, argv: []const []const u8, ) error{OutOfMemory}!void { - return handleVerbose2(b, opt_cwd, null, argv); + return handleVerbose2(b, cwd, null, argv); } pub fn handleVerbose2( b: *Build, - opt_cwd: ?[]const u8, + cwd: std.process.Child.Cwd, opt_env: ?*const std.process.Environ.Map, argv: []const []const u8, ) error{OutOfMemory}!void { @@ -716,7 +716,7 @@ pub fn handleVerbose2( const graph = b.graph; // Intention of verbose is to print all sub-process command lines to // stderr before spawning them. - const text = try allocPrintCmd(b.allocator, opt_cwd, if (opt_env) |env| .{ + const text = try allocPrintCmd(b.allocator, cwd, if (opt_env) |env| .{ .child = env, .parent = &graph.environ_map, } else null, argv); @@ -751,7 +751,7 @@ pub fn handleChildProcessTerm(s: *Step, term: std.process.Child.Term) error{ Mak pub fn allocPrintCmd( gpa: Allocator, - opt_cwd: ?[]const u8, + cwd: std.process.Child.Cwd, opt_env: ?struct { child: *const std.process.Environ.Map, parent: *const std.process.Environ.Map, @@ -796,7 +796,11 @@ pub fn allocPrintCmd( var aw: Io.Writer.Allocating = .init(gpa); defer aw.deinit(); const writer = &aw.writer; - if (opt_cwd) |cwd| writer.print("cd {s} && ", .{cwd}) catch return error.OutOfMemory; + switch (cwd) { + .inherit => {}, + .path => |path| writer.print("cd {s} && ", .{path}) catch return error.OutOfMemory, + .dir => @panic("TODO"), + } if (opt_env) |env| { var it = env.child.iterator(); while (it.next()) |entry| { diff --git a/lib/std/Build/Step/InstallArtifact.zig b/lib/std/Build/Step/InstallArtifact.zig index 019d465f01..c3c9d6c853 100644 --- a/lib/std/Build/Step/InstallArtifact.zig +++ b/lib/std/Build/Step/InstallArtifact.zig @@ -187,7 +187,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { const full_dest_path = b.pathJoin(&.{ full_h_prefix, entry.path }); switch (entry.kind) { .directory => { - try Step.handleVerbose(b, null, &.{ "install", "-d", full_dest_path }); + try Step.handleVerbose(b, .inherit, &.{ "install", "-d", full_dest_path }); const p = try step.installDir(full_dest_path); all_cached = all_cached and p == .existed; }, diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 68d0ec480c..3f5df9f2ae 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -1227,7 +1227,7 @@ fn runCommand( const gpa = options.gpa; const io = b.graph.io; - const cwd: ?[]const u8 = if (run.cwd) |lazy_cwd| lazy_cwd.getPath2(b, step) else null; + const cwd: process.Child.Cwd = if (run.cwd) |lazy_cwd| .{ .path = lazy_cwd.getPath2(b, step) } else .inherit; try step.handleChildProcUnsupported(); try Step.handleVerbose2(step.owner, cwd, run.environ_map, argv); @@ -1549,7 +1549,7 @@ fn spawnChildAndCollect( assert(run.stdio == .zig_test); } - const child_cwd = if (run.cwd) |lazy_cwd| lazy_cwd.getPath2(b, &run.step) else null; + const child_cwd: process.Child.Cwd = if (run.cwd) |lazy_cwd| .{ .path = lazy_cwd.getPath2(b, &run.step) } else .inherit; // If an error occurs, it's caused by this command: assert(run.step.result_failed_command == null); diff --git a/lib/std/Build/WebServer.zig b/lib/std/Build/WebServer.zig index 1f380b6c50..7205291400 100644 --- a/lib/std/Build/WebServer.zig +++ b/lib/std/Build/WebServer.zig @@ -652,7 +652,7 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim if (code != 0) { log.err( "the following command exited with error code {d}:\n{s}", - .{ code, try Build.Step.allocPrintCmd(arena, null, null, argv.items) }, + .{ code, try Build.Step.allocPrintCmd(arena, .inherit, null, argv.items) }, ); return error.WasmCompilationFailed; } @@ -660,14 +660,14 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim .signal => |sig| { log.err( "the following command terminated with signal {t}:\n{s}", - .{ sig, try Build.Step.allocPrintCmd(arena, null, null, argv.items) }, + .{ sig, try Build.Step.allocPrintCmd(arena, .inherit, null, argv.items) }, ); return error.WasmCompilationFailed; }, .stopped, .unknown => { log.err( "the following command terminated unexpectedly:\n{s}", - .{try Build.Step.allocPrintCmd(arena, null, null, argv.items)}, + .{try Build.Step.allocPrintCmd(arena, .inherit, null, argv.items)}, ); return error.WasmCompilationFailed; }, @@ -677,14 +677,14 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim try result_error_bundle.renderToStderr(io, .{}, .auto); log.err("the following command failed with {d} compilation errors:\n{s}", .{ result_error_bundle.errorMessageCount(), - try Build.Step.allocPrintCmd(arena, null, null, argv.items), + try Build.Step.allocPrintCmd(arena, .inherit, null, argv.items), }); return error.WasmCompilationFailed; } const base_path = result orelse { log.err("child process failed to report result\n{s}", .{ - try Build.Step.allocPrintCmd(arena, null, null, argv.items), + try Build.Step.allocPrintCmd(arena, .inherit, null, argv.items), }); return error.WasmCompilationFailed; }; diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 0feec928fc..298c3c167f 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -14606,10 +14606,14 @@ fn spawnPosix(t: *Threaded, options: process.SpawnOptions) process.SpawnError!Sp setUpChildIo(options.stdout, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkBail(ep1, err); setUpChildIo(options.stderr, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkBail(ep1, err); - if (options.cwd_dir) |cwd| { - fchdir(cwd.handle) catch |err| forkBail(ep1, err); - } else if (options.cwd) |cwd| { - chdir(cwd) catch |err| forkBail(ep1, err); + switch (options.cwd) { + .inherit => {}, + .dir => |cwd| { + fchdir(cwd.handle) catch |err| forkBail(ep1, err); + }, + .path => |cwd| { + chdir(cwd) catch |err| forkBail(ep1, err); + }, } // Must happen after fchdir above, the cwd file descriptor might be @@ -15193,7 +15197,28 @@ fn processSpawnWindows(userdata: ?*anyopaque, options: process.SpawnOptions) pro defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const cwd_w = if (options.cwd) |cwd| try std.unicode.wtf8ToWtf16LeAllocZ(arena, cwd) else null; + const cwd_w = cwd_w: { + switch (options.cwd) { + .inherit => break :cwd_w null, + .dir => |cwd_dir| { + var dir_path_buffer = try arena.alloc(u16, windows.PATH_MAX_WIDE + 1); + // TODO move GetFinalPathNameByHandle logic into std.Io.Threaded and add cancel checks + try Thread.checkCancel(); + const dir_path = try windows.GetFinalPathNameByHandle( + cwd_dir.handle, + .{}, + dir_path_buffer[0..windows.PATH_MAX_WIDE], + ); + dir_path_buffer[dir_path.len] = 0; + // Shrink the allocation down to just the path buffer + sentinel + dir_path_buffer = try arena.realloc(dir_path_buffer, dir_path.len + 1); + break :cwd_w dir_path_buffer[0..dir_path.len :0]; + }, + .path => |cwd| { + break :cwd_w try std.unicode.wtf8ToWtf16LeAllocZ(arena, cwd); + }, + } + }; const cwd_w_ptr = if (cwd_w) |cwd| cwd.ptr else null; const maybe_envp_buf = if (options.environ_map) |environ_map| try environ_map.createBlockWindows(arena) else null; @@ -15204,16 +15229,13 @@ fn processSpawnWindows(userdata: ?*anyopaque, options: process.SpawnOptions) pro // The cwd provided by options is in effect when choosing the executable // path to match POSIX semantics. - var cwd_path_w_needs_free = false; const cwd_path_w = x: { // If the app name is absolute, then we need to use its dirname as the cwd if (app_name_is_absolute) { - cwd_path_w_needs_free = true; const dir = Dir.path.dirname(app_name_wtf8).?; break :x try std.unicode.wtf8ToWtf16LeAllocZ(arena, dir); - } else if (options.cwd) |cwd| { - cwd_path_w_needs_free = true; - break :x try std.unicode.wtf8ToWtf16LeAllocZ(arena, cwd); + } else if (cwd_w) |cwd| { + break :x cwd; } else { break :x &[_:0]u16{}; // empty for cwd } diff --git a/lib/std/process.zig b/lib/std/process.zig index 3b5a0ecebd..d09239dbc2 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -359,17 +359,16 @@ pub const SpawnError = error{ /// children of the calling process and the child had already performed an /// image replacement. ProcessAlreadyExec, + /// On Windows, the volume does not contain a recognized file system. File + /// system drivers might not be loaded, or the volume may be corrupt. + UnrecognizedVolume, } || Io.Dir.PathNameError || Io.Cancelable || Io.UnexpectedError; pub const SpawnOptions = struct { argv: []const []const u8, /// Set to change the current working directory when spawning the child process. - cwd: ?[]const u8 = null, - /// Set to change the current working directory when spawning the child process. - /// This is not yet implemented for Windows. See https://github.com/ziglang/zig/issues/5190 - /// Once that is done, `cwd` will be deprecated in favor of this field. - cwd_dir: ?Io.Dir = null, + cwd: Child.Cwd = .inherit, /// Replaces the child environment when provided. The PATH value from here /// is not used to resolve `argv[0]`; that resolution always uses parent /// environment. @@ -465,11 +464,7 @@ pub const RunOptions = struct { reserve_amount: usize = 64, /// Set to change the current working directory when spawning the child process. - cwd: ?[]const u8 = null, - /// Set to change the current working directory when spawning the child process. - /// This is not yet implemented for Windows. See https://github.com/ziglang/zig/issues/5190 - /// Once that is done, `cwd` will be deprecated in favor of this field. - cwd_dir: ?Io.Dir = null, + cwd: Child.Cwd = .inherit, /// Replaces the child environment when provided. The PATH value from here /// is not used to resolve `argv[0]`; that resolution always uses parent /// environment. @@ -503,7 +498,6 @@ pub fn run(gpa: Allocator, io: Io, options: RunOptions) RunError!RunResult { var child = try spawn(io, .{ .argv = options.argv, .cwd = options.cwd, - .cwd_dir = options.cwd_dir, .environ_map = options.environ_map, .expand_arg0 = options.expand_arg0, .progress_node = options.progress_node, diff --git a/lib/std/process/Child.zig b/lib/std/process/Child.zig index c87d221a95..7ce3143b36 100644 --- a/lib/std/process/Child.zig +++ b/lib/std/process/Child.zig @@ -98,6 +98,17 @@ pub const Term = union(enum) { unknown: u32, }; +pub const Cwd = union(enum) { + /// CWD of the child is the same as the current CWD. + inherit, + /// On POSIX systems, `fchdir` is called after `fork` using this handle. + /// On Windows, the path is inferred from the provided handle and that path is used when calling `CreateProcessW`. + dir: Io.Dir, + /// On POSIX systems, `chdir` is called after `fork` using this path. + /// On Windows, this path is used when calling `CreateProcessW`. + path: []const u8, +}; + /// Requests for the operating system to forcibly terminate the child process, /// then blocks until it terminates, then cleans up all resources. /// diff --git a/test/standalone/windows_paths/test.zig b/test/standalone/windows_paths/test.zig index 1170de47ac..36f2a8be0e 100644 --- a/test/standalone/windows_paths/test.zig +++ b/test/standalone/windows_paths/test.zig @@ -32,39 +32,39 @@ pub fn main(init: std.process.Init) !void { // With the special =X: environment variable set, drive-relative paths that // don't match the CWD's drive letter are resolved against that env var. - try checkRelative(arena, io, "..\\..\\bar", &.{ exe_path, drive_rel, drive_abs }, null, &alt_drive_env_map); - try checkRelative(arena, io, "..\\baz\\foo", &.{ exe_path, drive_abs, drive_rel }, null, &alt_drive_env_map); + try checkRelative(arena, io, "..\\..\\bar", &.{ exe_path, drive_rel, drive_abs }, &alt_drive_env_map); + try checkRelative(arena, io, "..\\baz\\foo", &.{ exe_path, drive_abs, drive_rel }, &alt_drive_env_map); // Without that environment variable set, drive-relative paths that don't match the // CWD's drive letter are resolved against the root of the drive. - try checkRelative(arena, io, "..\\bar", &.{ exe_path, drive_rel, drive_abs }, null, &empty_env); - try checkRelative(arena, io, "..\\foo", &.{ exe_path, drive_abs, drive_rel }, null, &empty_env); + try checkRelative(arena, io, "..\\bar", &.{ exe_path, drive_rel, drive_abs }, &empty_env); + try checkRelative(arena, io, "..\\foo", &.{ exe_path, drive_abs, drive_rel }, &empty_env); // Bare drive-relative path with no components - try checkRelative(arena, io, "bar", &.{ exe_path, drive_rel[0..2], drive_abs }, null, &empty_env); - try checkRelative(arena, io, "..", &.{ exe_path, drive_abs, drive_rel[0..2] }, null, &empty_env); + try checkRelative(arena, io, "bar", &.{ exe_path, drive_rel[0..2], drive_abs }, &empty_env); + try checkRelative(arena, io, "..", &.{ exe_path, drive_abs, drive_rel[0..2] }, &empty_env); // Bare drive-relative path with no components, drive-CWD set - try checkRelative(arena, io, "..\\bar", &.{ exe_path, drive_rel[0..2], drive_abs }, null, &alt_drive_env_map); - try checkRelative(arena, io, "..\\baz", &.{ exe_path, drive_abs, drive_rel[0..2] }, null, &alt_drive_env_map); + try checkRelative(arena, io, "..\\bar", &.{ exe_path, drive_rel[0..2], drive_abs }, &alt_drive_env_map); + try checkRelative(arena, io, "..\\baz", &.{ exe_path, drive_abs, drive_rel[0..2] }, &alt_drive_env_map); // Bare drive-relative path relative to the CWD should be equivalent if drive-CWD is set - try checkRelative(arena, io, "", &.{ exe_path, alt_drive_cwd, drive_rel[0..2] }, null, &alt_drive_env_map); - try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], alt_drive_cwd }, null, &alt_drive_env_map); + try checkRelative(arena, io, "", &.{ exe_path, alt_drive_cwd, drive_rel[0..2] }, &alt_drive_env_map); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], alt_drive_cwd }, &alt_drive_env_map); // Bare drive-relative should always be equivalent to itself - try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &alt_drive_env_map); - try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &alt_drive_env_map); - try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &empty_env); - try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, null, &empty_env); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, &alt_drive_env_map); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, &alt_drive_env_map); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, &empty_env); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel[0..2], drive_rel[0..2] }, &empty_env); } if (parsed_cwd_path.kind == .unc_absolute) { const drive_abs_path = try std.fmt.allocPrint(arena, "{c}:\\foo\\bar", .{alt_drive_letter}); { - try checkRelative(arena, io, drive_abs_path, &.{ exe_path, cwd_path, drive_abs_path }, null, &empty_env); - try checkRelative(arena, io, cwd_path, &.{ exe_path, drive_abs_path, cwd_path }, null, &empty_env); + try checkRelative(arena, io, drive_abs_path, &.{ exe_path, cwd_path, drive_abs_path }, &empty_env); + try checkRelative(arena, io, cwd_path, &.{ exe_path, drive_abs_path, cwd_path }, &empty_env); } } else if (parsed_cwd_path.kind == .drive_absolute) { const cur_drive_letter = parsed_cwd_path.root[0]; @@ -72,14 +72,14 @@ pub fn main(init: std.process.Init) !void { const unc_cwd = try std.fmt.allocPrint(arena, "\\\\127.0.0.1\\{c}$\\{s}", .{ cur_drive_letter, path_beyond_root }); { - try checkRelative(arena, io, cwd_path, &.{ exe_path, unc_cwd, cwd_path }, null, &empty_env); - try checkRelative(arena, io, unc_cwd, &.{ exe_path, cwd_path, unc_cwd }, null, &empty_env); + try checkRelative(arena, io, cwd_path, &.{ exe_path, unc_cwd, cwd_path }, &empty_env); + try checkRelative(arena, io, unc_cwd, &.{ exe_path, cwd_path, unc_cwd }, &empty_env); } { const drive_abs = cwd_path; const drive_rel = parsed_cwd_path.root[0..2]; - try checkRelative(arena, io, "", &.{ exe_path, drive_abs, drive_rel }, null, &empty_env); - try checkRelative(arena, io, "", &.{ exe_path, drive_rel, drive_abs }, null, &empty_env); + try checkRelative(arena, io, "", &.{ exe_path, drive_abs, drive_rel }, &empty_env); + try checkRelative(arena, io, "", &.{ exe_path, drive_rel, drive_abs }, &empty_env); } } else { return error.UnexpectedPathType; @@ -91,12 +91,10 @@ fn checkRelative( io: Io, expected_stdout: []const u8, argv: []const []const u8, - cwd: ?[]const u8, environ_map: ?*const std.process.Environ.Map, ) !void { const result = try std.process.run(allocator, io, .{ .argv = argv, - .cwd = cwd, .environ_map = environ_map, }); defer allocator.free(result.stdout); diff --git a/test/standalone/windows_spawn/main.zig b/test/standalone/windows_spawn/main.zig index 4b37e3cf6e..18c9a68c57 100644 --- a/test/standalone/windows_spawn/main.zig +++ b/test/standalone/windows_spawn/main.zig @@ -207,10 +207,20 @@ fn testExecError(err: anyerror, gpa: Allocator, io: Io, command: []const u8) !vo } fn testExec(gpa: Allocator, io: Io, command: []const u8, expected_stdout: []const u8) !void { - return testExecWithCwd(gpa, io, command, null, expected_stdout); + return testExecWithCwdInner(gpa, io, command, .inherit, expected_stdout); } -fn testExecWithCwd(gpa: Allocator, io: Io, command: []const u8, cwd: ?[]const u8, expected_stdout: []const u8) !void { +fn testExecWithCwd(gpa: Allocator, io: Io, command: []const u8, cwd: []const u8, expected_stdout: []const u8) !void { + // Test by passing CWD as both a path and a Dir + try testExecWithCwdInner(gpa, io, command, .{ .path = cwd }, expected_stdout); + + var cwd_dir = try Io.Dir.cwd().openDir(io, cwd, .{}); + defer cwd_dir.close(io); + + try testExecWithCwdInner(gpa, io, command, .{ .dir = cwd_dir }, expected_stdout); +} + +fn testExecWithCwdInner(gpa: Allocator, io: Io, command: []const u8, cwd: std.process.Child.Cwd, expected_stdout: []const u8) !void { const result = try std.process.run(gpa, io, .{ .argv = &[_][]const u8{command}, .cwd = cwd, diff --git a/tools/doctest.zig b/tools/doctest.zig index 97a9a0be3f..0e29b2b983 100644 --- a/tools/doctest.zig +++ b/tools/doctest.zig @@ -199,7 +199,7 @@ fn printOutput( if (expected_outcome == .build_fail) { const result = try process.run(arena, io, .{ .argv = build_args.items, - .cwd = tmp_dir_path, + .cwd = .{ .path = tmp_dir_path }, .environ_map = environ_map, }); switch (result.term) { @@ -255,7 +255,7 @@ fn printOutput( const result = try process.run(arena, io, .{ .argv = run_args, .environ_map = environ_map, - .cwd = tmp_dir_path, + .cwd = .{ .path = tmp_dir_path }, }); switch (result.term) { .exited => |exit_code| { @@ -373,7 +373,7 @@ fn printOutput( const result = try process.run(arena, io, .{ .argv = test_args.items, .environ_map = environ_map, - .cwd = tmp_dir_path, + .cwd = .{ .path = tmp_dir_path }, }); switch (result.term) { .exited => |exit_code| { @@ -428,7 +428,7 @@ fn printOutput( const result = try process.run(arena, io, .{ .argv = test_args.items, .environ_map = environ_map, - .cwd = tmp_dir_path, + .cwd = .{ .path = tmp_dir_path }, }); switch (result.term) { .exited => |exit_code| { @@ -503,7 +503,7 @@ fn printOutput( const result = try process.run(arena, io, .{ .argv = build_args.items, .environ_map = environ_map, - .cwd = tmp_dir_path, + .cwd = .{ .path = tmp_dir_path }, }); switch (result.term) { .exited => |exit_code| { @@ -1126,7 +1126,7 @@ fn run( const result = try process.run(allocator, io, .{ .argv = args, .environ_map = environ_map, - .cwd = cwd, + .cwd = .{ .path = cwd }, }); switch (result.term) { .exited => |exit_code| { diff --git a/tools/incr-check.zig b/tools/incr-check.zig index 840faf6f27..171af57036 100644 --- a/tools/incr-check.zig +++ b/tools/incr-check.zig @@ -202,8 +202,7 @@ pub fn main(init: std.process.Init) !void { .stdout = .pipe, .stderr = .pipe, .progress_node = zig_prog_node, - .cwd_dir = tmp_dir, - .cwd = tmp_dir_path, + .cwd = .{ .path = tmp_dir_path }, }); defer child.kill(io); @@ -533,8 +532,7 @@ const Eval = struct { const result = std.process.run(eval.arena, io, .{ .argv = argv, - .cwd_dir = eval.tmp_dir, - .cwd = eval.tmp_dir_path, + .cwd = .{ .path = eval.tmp_dir_path }, }) catch |err| { if (is_foreign) { // Chances are the foreign executor isn't available. Skip this evaluation. @@ -626,8 +624,7 @@ const Eval = struct { const result = std.process.run(eval.arena, eval.io, .{ .argv = eval.cc_child_args.items, - .cwd_dir = eval.tmp_dir, - .cwd = eval.tmp_dir_path, + .cwd = .{ .path = eval.tmp_dir_path }, .progress_node = child_prog_node, }) catch |err| { eval.fatal("failed to spawn zig cc for '{s}': {t}", .{ c_path, err });