Commit 2737dce84f

Komari Spaghetti <jhc@dismail.de>
2023-02-21 18:26:55
Introduce ChildProcess.collectOutput (#12295)
All the code for this function already exists, but only ChildProcess.exec was allowed to use the code.
1 parent 7f691b3
Changed files (1)
lib/std/child_process.zig
@@ -197,6 +197,32 @@ pub const ChildProcess = struct {
         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(
         child: ChildProcess,
         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 outs = [_]*std.ArrayList(u8){
+            stdout,
+            stderr,
+        };
         const handles = [_]windows.HANDLE{
             child.stdout.?.handle,
             child.stderr.?.handle,
@@ -391,24 +421,6 @@ pub const ChildProcess = struct {
         child.env_map = args.env_map;
         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 stderr = std.ArrayList(u8).init(args.allocator);
         errdefer {
@@ -416,11 +428,8 @@ pub const ChildProcess = struct {
             stderr.deinit();
         }
 
-        if (builtin.os.tag == .windows) {
-            try collectOutputWindows(child, [_]*std.ArrayList(u8){ &stdout, &stderr }, args.max_output_bytes);
-        } else {
-            try collectOutputPosix(child, &stdout, &stderr, args.max_output_bytes);
-        }
+        try child.spawn();
+        try child.collectOutput(&stdout, &stderr, args.max_output_bytes);
 
         return ExecResult{
             .term = try child.wait(),