1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use std::collections::HashMap;
use deno_task_shell::{ShellPipeReader, ShellPipeWriter};
use mlua::{Lua, UserData};
use std::io::Read;
use crate::create_body;
#[doc(hidden)]
pub fn init(lua: &Lua) -> mlua::Result<mlua::Table> {
create_body!(lua,
"run_command" => lua.create_async_function(run_command)?,
"run_command_piped" => lua.create_async_function(run_command_piped)?
)
}
pub async fn run_command(_: &Lua, (command, cwd): (String, Option<String>)) -> mlua::Result<CommandResult> {
let list = deno_task_shell::parser::parse(&command).map_err(|x| mlua::Error::RuntimeError(x.to_string()))?;
let default_cwd = std::env::current_dir()?;
let cwd = cwd.map(|x| x.into()).unwrap_or(default_cwd);
let env_from_proc = std::env::vars().collect::<HashMap<String, String>>();
let (mut stdout, stdout_writer) = os_pipe::pipe()?;
let (mut stderr, stderr_writer) = os_pipe::pipe()?;
let stdin = ShellPipeReader::stdin();
let exit_code = deno_task_shell::execute_with_pipes(
list,
env_from_proc,
&cwd,
stdin,
ShellPipeWriter::OsPipe(stdout_writer),
ShellPipeWriter::OsPipe(stderr_writer),
)
.await;
let mut stdout_buffer = Vec::new();
let mut stderr_buffer = Vec::new();
stdout.read_to_end(&mut stdout_buffer)?;
stderr.read_to_end(&mut stderr_buffer)?;
let stdout = String::from_utf8(stdout_buffer)
.map_err(|x| mlua::Error::RuntimeError(format!("Failed to convert stdout to utf8: {x}")))?;
let stderr = String::from_utf8(stderr_buffer)
.map_err(|x| mlua::Error::RuntimeError(format!("Failed to convert stderr to utf8: {x}")))?;
Ok(CommandResult {
stdout,
stderr,
exit_code,
})
}
pub async fn run_command_piped(_: &Lua, (command, cwd): (String, Option<String>)) -> mlua::Result<i32> {
let list = deno_task_shell::parser::parse(&command).map_err(|x| mlua::Error::RuntimeError(x.to_string()))?;
let default_cwd = std::env::current_dir()?;
let cwd = cwd.map(|x| x.into()).unwrap_or(default_cwd);
let env_from_proc = std::env::vars().collect::<HashMap<String, String>>();
let exit_code = deno_task_shell::execute(list, env_from_proc, &cwd).await;
Ok(exit_code)
}
pub struct CommandResult {
pub stdout: String,
pub stderr: String,
pub exit_code: i32,
}
impl UserData for CommandResult {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("stdout", |_, this: &CommandResult| Ok(this.stdout.clone()));
fields.add_field_method_get("stderr", |_, this: &CommandResult| Ok(this.stderr.clone()));
fields.add_field_method_get("exit_code", |_, this: &CommandResult| Ok(this.exit_code));
}
}