| ... | @@ -344,15 +344,17 @@ pub const RunResult = struct { | ... | @@ -344,15 +344,17 @@ pub const RunResult = struct { |
| 344 | stderr: []u8, | 344 | stderr: []u8, |
| 345 | }; | 345 | }; |
| 346 | | 346 | |
| 347 | fn fifoToOwnedArrayList(fifo: *std.io.PollFifo) std.ArrayList(u8) { | 347 | fn writeFifoDataToArrayList(allocator: Allocator, list: *std.ArrayListUnmanaged(u8), fifo: *std.io.PollFifo) !void { |
| 348 | if (fifo.head != 0) fifo.realign(); | 348 | if (fifo.head != 0) fifo.realign(); |
| 349 | const result = std.ArrayList(u8){ | 349 | if (list.capacity == 0) { |
| 350 | .items = fifo.buf[0..fifo.count], | 350 | list.* = .{ |
| 351 | .capacity = fifo.buf.len, | 351 | .items = fifo.buf[0..fifo.count], |
| 352 | .allocator = fifo.allocator, | 352 | .capacity = fifo.buf.len, |
| 353 | }; | 353 | }; |
| 354 | fifo.* = std.io.PollFifo.init(fifo.allocator); | 354 | fifo.* = std.io.PollFifo.init(fifo.allocator); |
| 355 | return result; | 355 | } else { |
| | 356 | try list.appendSlice(allocator, fifo.buf[0..fifo.count]); |
| | 357 | } |
| 356 | } | 358 | } |
| 357 | | 359 | |
| 358 | /// Collect the output from the process's stdout and stderr. Will return once all output | 360 | /// Collect the output from the process's stdout and stderr. Will return once all output |
| ... | @@ -362,21 +364,16 @@ fn fifoToOwnedArrayList(fifo: *std.io.PollFifo) std.ArrayList(u8) { | ... | @@ -362,21 +364,16 @@ fn fifoToOwnedArrayList(fifo: *std.io.PollFifo) std.ArrayList(u8) { |
| 362 | /// The process must be started with stdout_behavior and stderr_behavior == .Pipe | 364 | /// The process must be started with stdout_behavior and stderr_behavior == .Pipe |
| 363 | pub fn collectOutput( | 365 | pub fn collectOutput( |
| 364 | child: ChildProcess, | 366 | child: ChildProcess, |
| 365 | stdout: *std.ArrayList(u8), | 367 | /// Used for `stdout` and `stderr`. |
| 366 | stderr: *std.ArrayList(u8), | 368 | allocator: Allocator, |
| | 369 | stdout: *std.ArrayListUnmanaged(u8), |
| | 370 | stderr: *std.ArrayListUnmanaged(u8), |
| 367 | max_output_bytes: usize, | 371 | max_output_bytes: usize, |
| 368 | ) !void { | 372 | ) !void { |
| 369 | assert(child.stdout_behavior == .Pipe); | 373 | assert(child.stdout_behavior == .Pipe); |
| 370 | assert(child.stderr_behavior == .Pipe); | 374 | assert(child.stderr_behavior == .Pipe); |
| 371 | | 375 | |
| 372 | // we could make this work with multiple allocators but YAGNI | 376 | var poller = std.io.poll(allocator, enum { stdout, stderr }, .{ |
| 373 | if (stdout.allocator.ptr != stderr.allocator.ptr or | | |
| 374 | stdout.allocator.vtable != stderr.allocator.vtable) | | |
| 375 | { | | |
| 376 | unreachable; // ChildProcess.collectOutput only supports 1 allocator | | |
| 377 | } | | |
| 378 | | | |
| 379 | var poller = std.io.poll(stdout.allocator, enum { stdout, stderr }, .{ | | |
| 380 | .stdout = child.stdout.?, | 377 | .stdout = child.stdout.?, |
| 381 | .stderr = child.stderr.?, | 378 | .stderr = child.stderr.?, |
| 382 | }); | 379 | }); |
| ... | @@ -389,8 +386,8 @@ pub fn collectOutput( | ... | @@ -389,8 +386,8 @@ pub fn collectOutput( |
| 389 | return error.StderrStreamTooLong; | 386 | return error.StderrStreamTooLong; |
| 390 | } | 387 | } |
| 391 | | 388 | |
| 392 | stdout.* = fifoToOwnedArrayList(poller.fifo(.stdout)); | 389 | try writeFifoDataToArrayList(allocator, stdout, poller.fifo(.stdout)); |
| 393 | stderr.* = fifoToOwnedArrayList(poller.fifo(.stderr)); | 390 | try writeFifoDataToArrayList(allocator, stderr, poller.fifo(.stderr)); |
| 394 | } | 391 | } |
| 395 | | 392 | |
| 396 | pub const RunError = posix.GetCwdError || posix.ReadError || SpawnError || posix.PollError || error{ | 393 | pub const RunError = posix.GetCwdError || posix.ReadError || SpawnError || posix.PollError || error{ |
| ... | @@ -420,22 +417,20 @@ pub fn run(args: struct { | ... | @@ -420,22 +417,20 @@ pub fn run(args: struct { |
| 420 | child.expand_arg0 = args.expand_arg0; | 417 | child.expand_arg0 = args.expand_arg0; |
| 421 | child.progress_node = args.progress_node; | 418 | child.progress_node = args.progress_node; |
| 422 | | 419 | |
| 423 | var stdout = std.ArrayList(u8).init(args.allocator); | 420 | var stdout: std.ArrayListUnmanaged(u8) = .empty; |
| 424 | var stderr = std.ArrayList(u8).init(args.allocator); | 421 | errdefer stdout.deinit(args.allocator); |
| 425 | errdefer { | 422 | var stderr: std.ArrayListUnmanaged(u8) = .empty; |
| 426 | stdout.deinit(); | 423 | errdefer stderr.deinit(args.allocator); |
| 427 | stderr.deinit(); | | |
| 428 | } | | |
| 429 | | 424 | |
| 430 | try child.spawn(); | 425 | try child.spawn(); |
| 431 | errdefer { | 426 | errdefer { |
| 432 | _ = child.kill() catch {}; | 427 | _ = child.kill() catch {}; |
| 433 | } | 428 | } |
| 434 | try child.collectOutput(&stdout, &stderr, args.max_output_bytes); | 429 | try child.collectOutput(args.allocator, &stdout, &stderr, args.max_output_bytes); |
| 435 | | 430 | |
| 436 | return RunResult{ | 431 | return RunResult{ |
| 437 | .stdout = try stdout.toOwnedSlice(), | 432 | .stdout = try stdout.toOwnedSlice(args.allocator), |
| 438 | .stderr = try stderr.toOwnedSlice(), | 433 | .stderr = try stderr.toOwnedSlice(args.allocator), |
| 439 | .term = try child.wait(), | 434 | .term = try child.wait(), |
| 440 | }; | 435 | }; |
| 441 | } | 436 | } |