| 448 | } |
| 449 | |
| 450 | async function drainToResult<E extends ExecEncoding>( |
| 451 | stream: ReadableStream<WorkspaceExecEvent<E>>, |
| 452 | encoding: E | undefined, |
| 453 | pushed: number, |
| 454 | postPull: Promise<PostPullOutcome>, |
| 455 | setReader: (reader: ReadableStreamDefaultReader<WorkspaceExecEvent<E>> | undefined) => void, |
| 456 | ): Promise<ExecResult<E>> { |
| 457 | const reader = stream.getReader(); |
| 458 | setReader(reader); |
| 459 | const stdoutParts: Array<Chunk<E>> = []; |
| 460 | const stderrParts: Array<Chunk<E>> = []; |
| 461 | let exitCode = -1; |
| 462 | try { |
| 463 | while (true) { |
| 464 | const { value, done } = await reader.read(); |
| 465 | if (done) break; |
| 466 | if (value.name === "stdout") stdoutParts.push(value.value); |
| 467 | else if (value.name === "stderr") stderrParts.push(value.value); |
| 468 | else exitCode = value.value; |
| 469 | } |
| 470 | } finally { |
| 471 | reader.releaseLock(); |
| 472 | setReader(undefined); |
| 473 | } |
| 474 | const pulled = await postPull; |
| 475 | return { |
| 476 | exitCode, |
| 477 | stdout: joinParts<E>(stdoutParts, encoding), |
| 478 | stderr: joinParts<E>(stderrParts, encoding), |
| 479 | pushed, |
| 480 | pulled: pulled.applied, |
| 481 | skipped: pulled.skipped, |
| 482 | sync: pulled.sync, |
| 483 | }; |
| 484 | } |
| 485 | |
| 486 | function joinParts<E extends ExecEncoding>( |
| 487 | parts: Array<Chunk<E>>, |