diff options
author | haturau <135221985+haturatu@users.noreply.github.com> | 2024-10-13 10:44:12 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-13 10:44:12 +0900 |
commit | cedfd657a6a2f04d841db2b3fc3d7694de95eada (patch) | |
tree | 0d5d1c95cfd35bc46c230ea71f4dbf23aa0aaeea /cli/task_runner.rs | |
parent | 4da77059dfd5b8d7591aa8e3b9f04386fbdce221 (diff) | |
parent | 64c304a45265705832ebb4ab4e9ef19f899ac911 (diff) |
Merge branch 'denoland:main' into main
Diffstat (limited to 'cli/task_runner.rs')
-rw-r--r-- | cli/task_runner.rs | 93 |
1 files changed, 85 insertions, 8 deletions
diff --git a/cli/task_runner.rs b/cli/task_runner.rs index ab7163bc9..418043b23 100644 --- a/cli/task_runner.rs +++ b/cli/task_runner.rs @@ -16,8 +16,11 @@ use deno_task_shell::ExecutableCommand; use deno_task_shell::ExecuteResult; use deno_task_shell::ShellCommand; use deno_task_shell::ShellCommandContext; +use deno_task_shell::ShellPipeReader; +use deno_task_shell::ShellPipeWriter; use lazy_regex::Lazy; use regex::Regex; +use tokio::task::JoinHandle; use tokio::task::LocalSet; use crate::npm::CliNpmResolver; @@ -36,6 +39,35 @@ pub fn get_script_with_args(script: &str, argv: &[String]) -> String { script.trim().to_owned() } +pub struct TaskStdio(Option<ShellPipeReader>, ShellPipeWriter); + +impl TaskStdio { + pub fn stdout() -> Self { + Self(None, ShellPipeWriter::stdout()) + } + pub fn stderr() -> Self { + Self(None, ShellPipeWriter::stderr()) + } + pub fn piped() -> Self { + let (r, w) = deno_task_shell::pipe(); + Self(Some(r), w) + } +} + +pub struct TaskIo { + pub stdout: TaskStdio, + pub stderr: TaskStdio, +} + +impl Default for TaskIo { + fn default() -> Self { + Self { + stderr: TaskStdio::stderr(), + stdout: TaskStdio::stdout(), + } + } +} + pub struct RunTaskOptions<'a> { pub task_name: &'a str, pub script: &'a str, @@ -45,24 +77,69 @@ pub struct RunTaskOptions<'a> { pub argv: &'a [String], pub custom_commands: HashMap<String, Rc<dyn ShellCommand>>, pub root_node_modules_dir: Option<&'a Path>, + pub stdio: Option<TaskIo>, } pub type TaskCustomCommands = HashMap<String, Rc<dyn ShellCommand>>; -pub async fn run_task(opts: RunTaskOptions<'_>) -> Result<i32, AnyError> { +pub struct TaskResult { + pub exit_code: i32, + pub stdout: Option<Vec<u8>>, + pub stderr: Option<Vec<u8>>, +} + +pub async fn run_task( + opts: RunTaskOptions<'_>, +) -> Result<TaskResult, AnyError> { let script = get_script_with_args(opts.script, opts.argv); let seq_list = deno_task_shell::parser::parse(&script) .with_context(|| format!("Error parsing script '{}'.", opts.task_name))?; let env_vars = prepare_env_vars(opts.env_vars, opts.init_cwd, opts.root_node_modules_dir); + let state = + deno_task_shell::ShellState::new(env_vars, opts.cwd, opts.custom_commands); + let stdio = opts.stdio.unwrap_or_default(); + let ( + TaskStdio(stdout_read, stdout_write), + TaskStdio(stderr_read, stderr_write), + ) = (stdio.stdout, stdio.stderr); + + fn read(reader: ShellPipeReader) -> JoinHandle<Result<Vec<u8>, AnyError>> { + tokio::task::spawn_blocking(move || { + let mut buf = Vec::new(); + reader.pipe_to(&mut buf)?; + Ok(buf) + }) + } + + let stdout = stdout_read.map(read); + let stderr = stderr_read.map(read); + let local = LocalSet::new(); - let future = deno_task_shell::execute( - seq_list, - env_vars, - opts.cwd, - opts.custom_commands, - ); - Ok(local.run_until(future).await) + let future = async move { + let exit_code = deno_task_shell::execute_with_pipes( + seq_list, + state, + ShellPipeReader::stdin(), + stdout_write, + stderr_write, + ) + .await; + Ok::<_, AnyError>(TaskResult { + exit_code, + stdout: if let Some(stdout) = stdout { + Some(stdout.await??) + } else { + None + }, + stderr: if let Some(stderr) = stderr { + Some(stderr.await??) + } else { + None + }, + }) + }; + local.run_until(future).await } fn prepare_env_vars( |