|
@@ -19,8 +19,8 @@ use env_logger::Builder;
|
|
|
use log::{debug, log_enabled, Level};
|
|
|
use serde::Deserialize;
|
|
|
use std::ffi::OsString;
|
|
|
-use std::io::Write;
|
|
|
-use std::process::{Command, Output};
|
|
|
+use std::io::{BufReader, Write};
|
|
|
+use std::process::{Command, ExitStatus, Stdio};
|
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
pub struct VersionMetadata {
|
|
@@ -104,11 +104,16 @@ where
|
|
|
.format_indent(Some(12))
|
|
|
.filter(None, level_from_usize(cli.verbose).to_level_filter())
|
|
|
.format(|f, record| {
|
|
|
+ let mut is_command_output = false;
|
|
|
if let Some(action) = record.key_values().get("action".into()) {
|
|
|
- let mut action_style = f.style();
|
|
|
- action_style.set_color(Color::Green).set_bold(true);
|
|
|
-
|
|
|
- write!(f, "{:>12} ", action_style.value(action.to_str().unwrap()))?;
|
|
|
+ let action = action.to_str().unwrap();
|
|
|
+ is_command_output = action == "stdout" || action == "stderr";
|
|
|
+ if !is_command_output {
|
|
|
+ let mut action_style = f.style();
|
|
|
+ action_style.set_color(Color::Green).set_bold(true);
|
|
|
+
|
|
|
+ write!(f, "{:>12} ", action_style.value(action))?;
|
|
|
+ }
|
|
|
} else {
|
|
|
let mut level_style = f.default_level_style(record.level());
|
|
|
level_style.set_bold(true);
|
|
@@ -120,7 +125,7 @@ where
|
|
|
)?;
|
|
|
}
|
|
|
|
|
|
- if log_enabled!(Level::Debug) {
|
|
|
+ if !is_command_output && log_enabled!(Level::Debug) {
|
|
|
let mut target_style = f.style();
|
|
|
target_style.set_color(Color::Black);
|
|
|
|
|
@@ -171,37 +176,61 @@ fn prettyprint_level(lvl: Level) -> &'static str {
|
|
|
pub trait CommandExt {
|
|
|
// The `pipe` function sets the stdout and stderr to properly
|
|
|
// show the command output in the Node.js wrapper.
|
|
|
- fn pipe(&mut self) -> Result<&mut Self>;
|
|
|
- fn output_ok(&mut self) -> crate::Result<Output>;
|
|
|
+ fn piped(&mut self) -> Result<ExitStatus>;
|
|
|
+ fn output_ok(&mut self) -> crate::Result<()>;
|
|
|
}
|
|
|
|
|
|
impl CommandExt for Command {
|
|
|
- fn pipe(&mut self) -> Result<&mut Self> {
|
|
|
+ fn piped(&mut self) -> crate::Result<ExitStatus> {
|
|
|
self.stdout(os_pipe::dup_stdout()?);
|
|
|
self.stderr(os_pipe::dup_stderr()?);
|
|
|
- Ok(self)
|
|
|
- }
|
|
|
+ let program = self.get_program().to_string_lossy().into_owned();
|
|
|
+ debug!(action = "Running"; "Command `{} {}`", program, self.get_args().map(|arg| arg.to_string_lossy()).fold(String::new(), |acc, arg| format!("{} {}", acc, arg)));
|
|
|
|
|
|
- fn output_ok(&mut self) -> crate::Result<Output> {
|
|
|
- debug!(action = "Running"; "Command `{} {}`", self.get_program().to_string_lossy(), self.get_args().map(|arg| arg.to_string_lossy()).fold(String::new(), |acc, arg| format!("{} {}", acc, arg)));
|
|
|
+ self.status().map_err(Into::into)
|
|
|
+ }
|
|
|
|
|
|
- let output = self.output()?;
|
|
|
+ fn output_ok(&mut self) -> crate::Result<()> {
|
|
|
+ let program = self.get_program().to_string_lossy().into_owned();
|
|
|
+ debug!(action = "Running"; "Command `{} {}`", program, self.get_args().map(|arg| arg.to_string_lossy()).fold(String::new(), |acc, arg| format!("{} {}", acc, arg)));
|
|
|
+
|
|
|
+ self.stdout(Stdio::piped());
|
|
|
+ self.stderr(Stdio::piped());
|
|
|
+
|
|
|
+ let mut child = self.spawn()?;
|
|
|
+
|
|
|
+ let mut stdout = child.stdout.take().map(BufReader::new).unwrap();
|
|
|
+ std::thread::spawn(move || {
|
|
|
+ let mut buf = Vec::new();
|
|
|
+ loop {
|
|
|
+ buf.clear();
|
|
|
+ match tauri_utils::io::read_line(&mut stdout, &mut buf) {
|
|
|
+ Ok(s) if s == 0 => break,
|
|
|
+ _ => (),
|
|
|
+ }
|
|
|
+ debug!(action = "stdout"; "{}", String::from_utf8_lossy(&buf));
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ let mut stderr = child.stderr.take().map(BufReader::new).unwrap();
|
|
|
+ std::thread::spawn(move || {
|
|
|
+ let mut buf = Vec::new();
|
|
|
+ loop {
|
|
|
+ buf.clear();
|
|
|
+ match tauri_utils::io::read_line(&mut stderr, &mut buf) {
|
|
|
+ Ok(s) if s == 0 => break,
|
|
|
+ _ => (),
|
|
|
+ }
|
|
|
+ debug!(action = "stderr"; "{}", String::from_utf8_lossy(&buf));
|
|
|
+ }
|
|
|
+ });
|
|
|
|
|
|
- let stdout = String::from_utf8_lossy(&output.stdout);
|
|
|
- if !stdout.is_empty() {
|
|
|
- debug!("Stdout: {}", stdout);
|
|
|
- }
|
|
|
- let stderr = String::from_utf8_lossy(&output.stderr);
|
|
|
- if !stderr.is_empty() {
|
|
|
- debug!("Stderr: {}", stderr);
|
|
|
- }
|
|
|
+ let status = child.wait()?;
|
|
|
|
|
|
- if output.status.success() {
|
|
|
- Ok(output)
|
|
|
+ if status.success() {
|
|
|
+ Ok(())
|
|
|
} else {
|
|
|
- Err(anyhow::anyhow!(
|
|
|
- String::from_utf8_lossy(&output.stderr).to_string()
|
|
|
- ))
|
|
|
+ Err(anyhow::anyhow!("failed to run {}", program))
|
|
|
}
|
|
|
}
|
|
|
}
|