Introduce ChildProcess.collectOutput (#12295)

All the code for this function already exists, but only
ChildProcess.exec was allowed to use the code.
This commit is contained in:
Komari Spaghetti 2023-02-21 18:26:55 +01:00 committed by GitHub
parent 7f691b3fe2
commit 2737dce84f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -197,6 +197,32 @@ pub const ChildProcess = struct {
stderr: []u8, stderr: []u8,
}; };
/// Collect the output from the process's stdout and stderr. Will return once all output
/// has been collected. This does not mean that the process has ended. `wait` should still
/// be called to wait for and clean up the process.
///
/// The process must be started with stdout_behavior and stderr_behavior == .Pipe
pub fn collectOutput(
child: ChildProcess,
stdout: *std.ArrayList(u8),
stderr: *std.ArrayList(u8),
max_output_bytes: usize,
) !void {
debug.assert(child.stdout_behavior == .Pipe);
debug.assert(child.stderr_behavior == .Pipe);
if (builtin.os.tag == .haiku) {
const stdout_in = child.stdout.?.reader();
const stderr_in = child.stderr.?.reader();
try stdout_in.readAllArrayList(stdout, max_output_bytes);
try stderr_in.readAllArrayList(stderr, max_output_bytes);
} else if (builtin.os.tag == .windows) {
try collectOutputWindows(child, stdout, stderr, max_output_bytes);
} else {
try collectOutputPosix(child, stdout, stderr, max_output_bytes);
}
}
fn collectOutputPosix( fn collectOutputPosix(
child: ChildProcess, child: ChildProcess,
stdout: *std.ArrayList(u8), stdout: *std.ArrayList(u8),
@ -297,8 +323,12 @@ pub const ChildProcess = struct {
} }
} }
fn collectOutputWindows(child: ChildProcess, outs: [2]*std.ArrayList(u8), max_output_bytes: usize) !void { fn collectOutputWindows(child: ChildProcess, stdout: *std.ArrayList(u8), stderr: *std.ArrayList(u8), max_output_bytes: usize) !void {
const bump_amt = 512; const bump_amt = 512;
const outs = [_]*std.ArrayList(u8){
stdout,
stderr,
};
const handles = [_]windows.HANDLE{ const handles = [_]windows.HANDLE{
child.stdout.?.handle, child.stdout.?.handle,
child.stderr.?.handle, child.stderr.?.handle,
@ -391,24 +421,6 @@ pub const ChildProcess = struct {
child.env_map = args.env_map; child.env_map = args.env_map;
child.expand_arg0 = args.expand_arg0; child.expand_arg0 = args.expand_arg0;
try child.spawn();
if (builtin.os.tag == .haiku) {
const stdout_in = child.stdout.?.reader();
const stderr_in = child.stderr.?.reader();
const stdout = try stdout_in.readAllAlloc(args.allocator, args.max_output_bytes);
errdefer args.allocator.free(stdout);
const stderr = try stderr_in.readAllAlloc(args.allocator, args.max_output_bytes);
errdefer args.allocator.free(stderr);
return ExecResult{
.term = try child.wait(),
.stdout = stdout,
.stderr = stderr,
};
}
var stdout = std.ArrayList(u8).init(args.allocator); var stdout = std.ArrayList(u8).init(args.allocator);
var stderr = std.ArrayList(u8).init(args.allocator); var stderr = std.ArrayList(u8).init(args.allocator);
errdefer { errdefer {
@ -416,11 +428,8 @@ pub const ChildProcess = struct {
stderr.deinit(); stderr.deinit();
} }
if (builtin.os.tag == .windows) { try child.spawn();
try collectOutputWindows(child, [_]*std.ArrayList(u8){ &stdout, &stderr }, args.max_output_bytes); try child.collectOutput(&stdout, &stderr, args.max_output_bytes);
} else {
try collectOutputPosix(child, &stdout, &stderr, args.max_output_bytes);
}
return ExecResult{ return ExecResult{
.term = try child.wait(), .term = try child.wait(),