Skip to content

Commit

Permalink
feat: support output fd redirects for stdout and stderr (#111)
Browse files Browse the repository at this point in the history
  • Loading branch information
dsherret authored Mar 21, 2024
1 parent 32580d9 commit 7d0e506
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 13 deletions.
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.

#![deny(clippy::print_stderr)]
#![deny(clippy::print_stdout)]
#![deny(clippy::unused_async)]

pub mod parser;

#[cfg(feature = "shell")]
Expand Down
46 changes: 36 additions & 10 deletions src/shell/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ async fn execute_pipeline_inner(
}
}

#[derive(Debug)]
enum RedirectPipe {
Input(ShellPipeReader),
Output(ShellPipeWriter),
Expand All @@ -358,6 +359,39 @@ async fn resolve_redirect_pipe(
redirect: &Redirect,
state: &ShellState,
stdin: &ShellPipeReader,
stdout: &ShellPipeWriter,
stderr: &mut ShellPipeWriter,
) -> Result<RedirectPipe, ExecuteResult> {
match redirect.io_file.clone() {
IoFile::Word(word) => {
resolve_redirect_word_pipe(word, &redirect.op, state, stdin, stderr).await
}
IoFile::Fd(fd) => match &redirect.op {
RedirectOp::Input(RedirectOpInput::Redirect) => {
let _ = stderr.write_line(
"deno_task_shell: input redirecting file descriptors is not implemented",
);
Err(ExecuteResult::from_exit_code(1))
}
RedirectOp::Output(_op) => match fd {
1 => Ok(RedirectPipe::Output(stdout.clone())),
2 => Ok(RedirectPipe::Output(stderr.clone())),
_ => {
let _ = stderr.write_line(
"deno_task_shell: output redirecting file descriptors beyond stdout and stderr is not implemented",
);
Err(ExecuteResult::from_exit_code(1))
}
},
},
}
}

async fn resolve_redirect_word_pipe(
word: Word,
redirect_op: &RedirectOp,
state: &ShellState,
stdin: &ShellPipeReader,
stderr: &mut ShellPipeWriter,
) -> Result<RedirectPipe, ExecuteResult> {
fn handle_std_result(
Expand All @@ -378,15 +412,6 @@ async fn resolve_redirect_pipe(
}
}

let word = match redirect.io_file.clone() {
IoFile::Word(word) => word,
IoFile::Fd(_) => {
let _ = stderr.write_line(
"deno_task_shell: redirecting file descriptors is not implemented",
);
return Err(ExecuteResult::from_exit_code(1));
}
};
let words = evaluate_word_parts(
word.into_parts(),
state,
Expand Down Expand Up @@ -417,7 +442,7 @@ async fn resolve_redirect_pipe(
}
let output_path = &words[0];

match &redirect.op {
match &redirect_op {
RedirectOp::Input(RedirectOpInput::Redirect) => {
let output_path = state.cwd().join(output_path);
let std_file_result =
Expand Down Expand Up @@ -458,6 +483,7 @@ async fn execute_command(
redirect,
&state,
&stdin,
&stdout,
&mut stderr,
)
.await
Expand Down
27 changes: 24 additions & 3 deletions src/shell/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -588,13 +588,34 @@ async fn redirects_output() {
.await;

TestBuilder::new()
.command(r#"echo 1 >&2"#)
.command(r#"echo 1 >&3"#)
.assert_stderr(
"deno_task_shell: redirecting file descriptors is not implemented\n",
"deno_task_shell: output redirecting file descriptors beyond stdout and stderr is not implemented\n",
)
.assert_exit_code(1)
.run()
.await;

TestBuilder::new()
.command(r#"echo 1 >&1"#)
.assert_stdout("1\n")
.assert_exit_code(0)
.run()
.await;

TestBuilder::new()
.command(r#"echo 1 >&2"#)
.assert_stderr("1\n")
.assert_exit_code(0)
.run()
.await;

TestBuilder::new()
.command(r#"deno eval 'console.error(2)' 2>&1"#)
.assert_stdout("2\n")
.assert_exit_code(0)
.run()
.await;
}

#[tokio::test]
Expand All @@ -616,7 +637,7 @@ async fn redirects_input() {
TestBuilder::new()
.command(r#"cat - <&0"#)
.assert_stderr(
"deno_task_shell: redirecting file descriptors is not implemented\n",
"deno_task_shell: input redirecting file descriptors is not implemented\n",
)
.assert_exit_code(1)
.run()
Expand Down
2 changes: 2 additions & 0 deletions src/shell/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ impl ExecuteResult {
}

/// Reader side of a pipe.
#[derive(Debug)]
pub enum ShellPipeReader {
OsPipe(os_pipe::PipeReader),
StdFile(std::fs::File),
Expand Down Expand Up @@ -300,6 +301,7 @@ impl ShellPipeReader {
///
/// Ensure that all of these are dropped when complete in order to
/// prevent deadlocks where the reader hangs waiting for a read.
#[derive(Debug)]
pub enum ShellPipeWriter {
OsPipe(os_pipe::PipeWriter),
StdFile(std::fs::File),
Expand Down

0 comments on commit 7d0e506

Please sign in to comment.