Implement command module
This commit is contained in:
parent
d0a14d7763
commit
f3e965394e
@ -1,31 +1,93 @@
|
|||||||
use crate::logger::Logger;
|
use crate::log;
|
||||||
|
use crate::logger::{LogLevel, Logger};
|
||||||
|
use std::error::Error;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::process::{Command, ExitStatus};
|
use std::process::{Command, ExitStatus, Stdio};
|
||||||
|
|
||||||
pub trait LogRunnable {
|
pub trait LogRunnable {
|
||||||
fn run(&mut self, logger: &Logger) -> Result<(), ExecutionError>;
|
fn run(&mut self, logger: &Logger) -> Result<(), ExecutionError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LogRunnable for Command {
|
impl LogRunnable for Command {
|
||||||
//TODO use specific execution error as error type
|
fn run(&mut self, logger: &Logger) -> Result<(), SpecificExecutionError> {
|
||||||
fn run(&mut self, logger: &Logger) -> Result<(), ExecutionError> {
|
//TODO I'm not happy yet with the implementation of this method
|
||||||
todo!("depending on log level, pipe output and only print with logger on error")
|
match logger.level {
|
||||||
|
LogLevel::Debug | LogLevel::Info => self
|
||||||
|
.status()
|
||||||
|
.map_err(ExecutionError::StartError)
|
||||||
|
.and_then(|status| {
|
||||||
|
if status.success() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(ExecutionError::BadExitStatus(status))
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
LogLevel::Error => self
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.output()
|
||||||
|
.map_err(ExecutionError::StartError)
|
||||||
|
.and_then(|output| {
|
||||||
|
if output.status.success() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
log!(logger, error, "{}", String::from_utf8_lossy(&output.stderr));
|
||||||
|
Err(ExecutionError::BadExitStatus(output.status))
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
.map_err(|error| SpecificExecutionError {
|
||||||
|
command: self,
|
||||||
|
error,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO show command in specific execution error
|
#[derive(Debug)]
|
||||||
|
pub struct SpecificExecutionError<'a> {
|
||||||
|
pub command: &'a Command,
|
||||||
|
pub error: ExecutionError,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for SpecificExecutionError<'_> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"Failed to execute command {}: {}",
|
||||||
|
self.command, self.error
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for SpecificExecutionError<'_> {}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ExecutionError {
|
pub enum ExecutionError {
|
||||||
StartError(io::Error),
|
StartError(io::Error),
|
||||||
BadExitStatus(ExitStatus),
|
BadExitStatus(ExitStatus),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for ExecutionError {
|
||||||
|
fn from(value: io::Error) -> Self {
|
||||||
|
Self::StartError(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ExitStatus> for ExecutionError {
|
||||||
|
fn from(value: ExitStatus) -> Self {
|
||||||
|
Self::BadExitStatus(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for ExecutionError {
|
impl Display for ExecutionError {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
ExecutionError::StartError(e) => write!(f, "failed to start command: {}", e),
|
ExecutionError::StartError(e) => write!(f, "failed to start command: {}", e),
|
||||||
ExecutionError::BadExitStatus(status) => write!(f, "command failed with exit status: {}", status),
|
ExecutionError::BadExitStatus(status) => {
|
||||||
|
write!(f, "command failed with exit status: {}", status)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Error for ExecutionError {}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user