feat: support redirects in pipe sequence commands#177
Conversation
The parser previously rejected redirects on any command in a pipe sequence (e.g. `cmd 2>&1 | tee log`), even though the AST already carries a per-command `redirect` and the executor's `execute_command` applies it before dispatching to `execute_simple_command` / `execute_subshell`. Drop the parser bailout so common bash idioms like `cmd 2>&1 | reader` and `cmd > file | reader` parse and execute. Fixes denoland/deno#28808.
bartlomieju
left a comment
There was a problem hiding this comment.
Reviewed — clean, correct, and well-tested. I traced the executor to confirm the central claim, and the semantics match bash exactly.
The fix is sound. The parser bailout was overly conservative; the executor already handles per-command redirects inside a pipe sequence:
execute_pipe_sequenceassigns each command's stdout to the pipe writer, then callsexecute_command.execute_commandresolves the per-commandredirectafter the pipe stdout is assigned, then reassigns the fds.
This ordering is exactly bash's model (pipe redirection first, then the command's own redirects), so both cases come out right:
echo 1 > output.txt | cat— pipe sets echo's stdout to the pipe, then> output.txtoverrides fd 1 to the file; the pipe writer drops, socatgets EOF (len=0). ✓... 2>&1 | reader—resolve_redirect_pipeforIoFile::Fd(1)returns the stdout writer, which is the pipe, so fd 2 → pipe; both streams funnel through (o\ne). ✓
Tests improved. The negative parser test is replaced by two positive parser tests (full AST) plus two deterministic end-to-end integration tests covering the redirect-vs-pipe ordering.
Minor: input/middle-command redirects (a | cmd < input | reader) are now also permitted — correct bash behavior and the executor handles it, though not covered by a test. Non-blocking.
One gate note: CI shows "no checks found" — worth confirming the workflows actually run before merge.
@bartlomieju this is ready to merge (pending CI).
The parser previously rejected redirects on any command in a pipe
sequence (e.g.
cmd 2>&1 | tee log), even though the AST'sCommandnode already carries a per-command
redirectand the executor'sexecute_commandapplies it before dispatching toexecute_simple_command/
execute_subshell. Drop the parser bailout inparse_pipeline_innerso common bash idioms like
cmd 2>&1 | readerandcmd > file | readerparse and execute.
The existing negative parser test that asserted the error message is
replaced with two positive parser tests covering
echo 1 1> stdout.txt | catandcmd 2>&1 | tee log. Two integration tests exercise theruntime behavior end-to-end: that the left side's stdout redirect makes
the right side receive an empty pipe, and that
2>&1 |correctlyfunnels both stdout and stderr into the pipe.
Fixes denoland/deno#28808.