Implement ShellInterface for EnvCommand

This commit is contained in:
Leonard Steppy 2025-02-05 21:16:45 +01:00
parent 4095ee32f6
commit 6b0b648d67
2 changed files with 67 additions and 20 deletions

View File

@ -16,6 +16,7 @@ use crate::logger::{LogLevel, Logger};
use crate::os_str_extension::OsStrExtension; use crate::os_str_extension::OsStrExtension;
use crate::os_string_builder::ReplaceWithOsStr; use crate::os_string_builder::ReplaceWithOsStr;
use crate::server::{RelativeLocalPathAnker, ServerAddress}; use crate::server::{RelativeLocalPathAnker, ServerAddress};
use crate::shell_interface::os_string_from_ssh_output;
use clap::{Parser, Subcommand, ValueEnum}; use clap::{Parser, Subcommand, ValueEnum};
use lazy_regex::{lazy_regex, Lazy, Regex}; use lazy_regex::{lazy_regex, Lazy, Regex};
use server::{Server, ServerReference}; use server::{Server, ServerReference};
@ -243,7 +244,7 @@ where
))?; ))?;
} }
let denoted_files = osstring_from_ssh_output(output.stdout) let denoted_files = os_string_from_ssh_output(output.stdout)
.split(b'\n') //split at line breaks .split(b'\n') //split at line breaks
.into_iter() .into_iter()
.filter(|bytes| !bytes.is_empty()) //needed since realpath sometimes gives us empty lines .filter(|bytes| !bytes.is_empty()) //needed since realpath sometimes gives us empty lines
@ -304,7 +305,7 @@ where
server, server,
actions: { actions: {
let present_file_names: Vec<OsString> = match &server.address { let present_file_names: Vec<OsString> = match &server.address {
ServerAddress::Ssh { ssh_address } => osstring_from_ssh_output( ServerAddress::Ssh { ssh_address } => os_string_from_ssh_output(
ShellCmd::new("ssh") ShellCmd::new("ssh")
.arg(ssh_address) .arg(ssh_address)
.arg(osf!("ls ") + &working_directory) .arg(osf!("ls ") + &working_directory)
@ -735,21 +736,6 @@ fn main() -> Result<(), String> {
Application::<Prod>::default().run() Application::<Prod>::default().run()
} }
//This will be moved into the shell-interface
fn osstring_from_ssh_output(output: Vec<u8>) -> OsString {
#[cfg(unix)]
{
use std::os::unix::ffi::OsStringExt;
OsString::from_vec(output)
}
#[cfg(windows)]
{
use std::os::windows::ffi::OsStringExt;
OsString::from_wide(output.iter().map(|&b| b as u16).collect())
}
}
fn parse_server_configuration<F>( fn parse_server_configuration<F>(
config_str: &str, config_str: &str,
get_home_directory: F, get_home_directory: F,

View File

@ -3,10 +3,10 @@ use crate::logger::{LogLevel, Logger};
use std::error::Error; use std::error::Error;
use std::ffi::OsString; use std::ffi::OsString;
use std::fmt::{Debug, Display, Formatter}; use std::fmt::{Debug, Display, Formatter};
use std::io;
use std::iter::once; use std::iter::once;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Command; use std::process::{Command, Output};
use std::{io, process};
#[derive(Debug)] #[derive(Debug)]
pub struct EnvCommand<'a, E> { pub struct EnvCommand<'a, E> {
@ -123,7 +123,27 @@ pub trait ShellInterface {
} }
} }
//TODO implement shell interface for env command impl<E> ShellInterface for EnvCommand<'_, E> {
fn run(self) -> CommandResult<ExitStatus, StartError> {
CommandResult {
result: build_command_from_shell_command(&self.command)
.status()
.map(ExitStatus::from)
.map_err(StartError),
command: self.command,
}
}
fn output(self) -> CommandResult<CommandOutput, StartError> {
CommandResult {
result: build_command_from_shell_command(&self.command)
.output()
.map(CommandOutput::from)
.map_err(StartError),
command: self.command,
}
}
}
pub trait MaybeCast<T> { pub trait MaybeCast<T> {
fn maybe_cast(&self) -> Option<&T>; fn maybe_cast(&self) -> Option<&T>;
@ -234,6 +254,31 @@ pub struct CommandOutput {
pub status: ExitStatus, pub status: ExitStatus,
} }
impl From<Output> for CommandOutput {
fn from(value: Output) -> Self {
Self {
stdout: os_string_from_ssh_output(value.stdout),
stderr: os_string_from_ssh_output(value.stderr),
status: value.status.into(),
}
}
}
//TODO remove super visibility once it is not needed anymore
pub(super) fn os_string_from_ssh_output(output: Vec<u8>) -> OsString {
#[cfg(unix)]
{
use std::os::unix::ffi::OsStringExt;
OsString::from_vec(output)
}
#[cfg(windows)]
{
use std::os::windows::ffi::OsStringExt;
OsString::from_wide(output.iter().map(|&b| b as u16).collect())
}
}
impl AsRef<ExitStatus> for CommandOutput { impl AsRef<ExitStatus> for CommandOutput {
fn as_ref(&self) -> &ExitStatus { fn as_ref(&self) -> &ExitStatus {
&self.status &self.status
@ -247,6 +292,16 @@ pub struct ExitStatus {
pub code: Option<i32>, pub code: Option<i32>,
} }
impl From<process::ExitStatus> for ExitStatus {
fn from(value: process::ExitStatus) -> Self {
Self {
success: value.success(),
string_form: value.to_string(),
code: value.code(),
}
}
}
impl AsRef<ExitStatus> for ExitStatus { impl AsRef<ExitStatus> for ExitStatus {
fn as_ref(&self) -> &ExitStatus { fn as_ref(&self) -> &ExitStatus {
self self
@ -283,6 +338,12 @@ impl<E> Error for CommandError<E> where E: Error {}
#[derive(Debug)] #[derive(Debug)]
pub struct StartError(io::Error); pub struct StartError(io::Error);
impl From<io::Error> for StartError {
fn from(value: io::Error) -> Self {
StartError(value)
}
}
impl Display for StartError { impl Display for StartError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "Failed to run command: {}", self.0) write!(f, "Failed to run command: {}", self.0)