2022-12-16 23:44:35 -05:00
|
|
|
use anyhow::bail;
|
|
|
|
use anyhow::Context;
|
|
|
|
use anyhow::Result;
|
2022-12-15 23:19:17 -05:00
|
|
|
use std::{
|
|
|
|
io::Write,
|
|
|
|
process::{Command, Stdio},
|
|
|
|
};
|
|
|
|
|
|
|
|
use crate::App;
|
|
|
|
|
2022-12-16 21:28:40 -05:00
|
|
|
pub struct CommandResult {
|
2022-12-15 23:19:17 -05:00
|
|
|
pub status_success: bool,
|
2022-12-16 21:28:40 -05:00
|
|
|
pub stdout: Vec<u8>,
|
|
|
|
pub stderr: Vec<u8>,
|
2022-12-15 23:19:17 -05:00
|
|
|
}
|
|
|
|
|
2022-12-16 21:28:40 -05:00
|
|
|
impl Default for CommandResult {
|
2022-12-15 23:19:17 -05:00
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
status_success: true,
|
2022-12-16 21:28:40 -05:00
|
|
|
stdout: vec![],
|
|
|
|
stderr: vec![],
|
2022-12-15 23:19:17 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn run(app: &mut App) {
|
2022-12-17 11:25:15 -05:00
|
|
|
match run_inner(app) {
|
|
|
|
Ok(c) => {
|
|
|
|
// If there was no stdout and the command failed, don't touch stdout
|
|
|
|
if !c.status_success && c.stdout.is_empty() {
|
|
|
|
app.command_result.stderr = c.stderr;
|
|
|
|
app.command_result.status_success = c.status_success;
|
|
|
|
} else {
|
|
|
|
app.command_result = c;
|
|
|
|
}
|
|
|
|
}
|
2022-12-16 20:41:16 -05:00
|
|
|
Err(e) => {
|
2022-12-17 11:25:15 -05:00
|
|
|
println!("asdf");
|
|
|
|
app.command_result.status_success = false;
|
|
|
|
app.command_result.stderr = e.to_string().as_bytes().to_vec();
|
2022-12-16 20:41:16 -05:00
|
|
|
}
|
2022-12-17 11:25:15 -05:00
|
|
|
}
|
|
|
|
}
|
2022-12-16 20:41:16 -05:00
|
|
|
|
2022-12-17 11:25:15 -05:00
|
|
|
fn run_inner(app: &mut App) -> Result<CommandResult> {
|
|
|
|
let mut command = Command::new(&app.command);
|
|
|
|
command
|
2022-12-15 23:19:17 -05:00
|
|
|
.stdin(Stdio::piped())
|
|
|
|
.stdout(Stdio::piped())
|
|
|
|
.stderr(Stdio::piped())
|
2022-12-17 11:25:15 -05:00
|
|
|
.args(&app.hidden_options);
|
|
|
|
|
|
|
|
if app.wordsplit {
|
|
|
|
match shellwords::split(&app.cmdline) {
|
|
|
|
Ok(a) => {
|
|
|
|
command.args(a);
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
bail!("Argument error: {e:?}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// TODO: Avoid cloning here
|
|
|
|
command.arg(&app.cmdline);
|
|
|
|
}
|
|
|
|
let mut child = command.spawn().context("Could not spawn child process")?;
|
2022-12-15 23:19:17 -05:00
|
|
|
|
2022-12-16 23:44:35 -05:00
|
|
|
let mut stdin = child.stdin.take().context("Could not take stdin")?;
|
2022-12-15 23:19:17 -05:00
|
|
|
let text_orig_clone = app.text_orig.clone();
|
|
|
|
std::thread::spawn(move || {
|
2022-12-17 00:10:17 -05:00
|
|
|
let _result = stdin.write_all(text_orig_clone.as_bytes());
|
2022-12-15 23:19:17 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
// Collect the output
|
2022-12-16 23:44:35 -05:00
|
|
|
let output = child.wait_with_output().context("Failed to read stdout")?;
|
2022-12-15 23:19:17 -05:00
|
|
|
|
2022-12-16 23:44:35 -05:00
|
|
|
Ok(CommandResult {
|
2022-12-15 23:19:17 -05:00
|
|
|
status_success: output.status.success(),
|
2022-12-16 21:28:40 -05:00
|
|
|
stdout: output.stdout,
|
|
|
|
stderr: output.stderr,
|
2022-12-16 23:44:35 -05:00
|
|
|
})
|
2022-12-15 23:19:17 -05:00
|
|
|
}
|