Compare commits

..

No commits in common. "1230a3ea07706c92b88ef60606f4e91e6f0f3129" and "d963d4ff889983c2707e76c6a6cbdfe5e214ed33" have entirely different histories.

4 changed files with 60 additions and 132 deletions

View File

@ -1,13 +1,9 @@
use crate::shell_interface::{
build_command_from_shell_command, CommandOutput, CommandResult, ExitStatus, ShellCommand,
ShellInterface, StartError,
};
use std::env::VarError;
use std::ffi::{OsStr, OsString};
use std::path::PathBuf;
use std::{env, io};
pub trait Environment: ShellInterface {
pub trait Environment {
fn args_os(&self) -> Vec<OsString>;
fn var<K>(&self, key: K) -> Result<String, VarError>
where
@ -36,9 +32,9 @@ impl Environment for Prod {
}
fn set_var<K, V>(&mut self, key: K, value: V)
where
K: AsRef<OsStr>,
V: AsRef<OsStr>,
where
K: AsRef<OsStr>,
V: AsRef<OsStr>
{
env::set_var(key, value);
}
@ -53,28 +49,3 @@ impl Environment for Prod {
Ok(buffer.trim().to_string())
}
}
impl ShellInterface for Prod {
fn run_command(&mut self, command: ShellCommand) -> CommandResult<ExitStatus, StartError> {
CommandResult {
result: build_command_from_shell_command(&command)
.status()
.map(ExitStatus::from)
.map_err(StartError::from),
command,
}
}
fn collect_command_output(
&mut self,
command: ShellCommand,
) -> CommandResult<CommandOutput, StartError> {
CommandResult {
result: build_command_from_shell_command(&command)
.output()
.map(CommandOutput::from)
.map_err(StartError::from),
command,
}
}
}

View File

@ -1,52 +0,0 @@
use crate::environment::Environment;
use crate::shell_interface::{
CommandOutput, CommandResult, ExitStatus, ShellCommand, ShellInterface, StartError,
};
use std::env::VarError;
use std::ffi::{OsStr, OsString};
use std::io::Error;
use std::path::PathBuf;
struct TestEnvironment {}
impl Environment for TestEnvironment {
fn args_os(&self) -> Vec<OsString> {
todo!()
}
fn var<K>(&self, key: K) -> Result<String, VarError>
where
K: AsRef<OsStr>,
{
todo!()
}
fn set_var<K, V>(&mut self, key: K, value: V)
where
K: AsRef<OsStr>,
V: AsRef<OsStr>,
{
todo!()
}
fn get_home_directory(&self) -> Option<PathBuf> {
todo!()
}
fn read_line(&mut self) -> Result<String, Error> {
todo!()
}
}
impl ShellInterface for TestEnvironment {
fn run_command(&mut self, command: ShellCommand) -> CommandResult<ExitStatus, StartError> {
todo!()
}
fn collect_command_output(
&mut self,
command: ShellCommand,
) -> CommandResult<CommandOutput, StartError> {
todo!()
}
}

View File

@ -1,8 +1,6 @@
mod action;
mod environment;
mod file;
#[cfg(test)]
mod integration_test;
mod logger;
mod os_str_extension;
mod os_string_builder;
@ -16,7 +14,7 @@ use crate::logger::{LogLevel, Logger};
use crate::os_str_extension::OsStrExtension;
use crate::os_string_builder::ReplaceWithOsStr;
use crate::server::{RelativeLocalPathAnker, ServerAddress};
use crate::shell_interface::{ScpParam, ServerCommand, ShellCommand};
use crate::shell_interface::{ScpParam, ServerCommand, ShellCommand, ShellInterface};
use clap::{Parser, Subcommand, ValueEnum};
use lazy_regex::{lazy_regex, Lazy, Regex};
use server::{Server, ServerReference};

View File

@ -5,6 +5,7 @@ use std::error::Error;
use std::ffi::OsString;
use std::fmt::{Debug, Display, Formatter};
use std::iter::once;
use std::marker::PhantomData;
use std::path::{Path, PathBuf};
use std::process::{Command, Output};
use std::{io, process};
@ -12,44 +13,11 @@ use std::{io, process};
#[derive(Debug)]
pub struct EnvCommand<'a, E> {
command: ShellCommand,
phantom_data: PhantomData<&'a E>,
#[cfg(test)]
environment: &'a mut E,
}
impl<E> EnvCommand<'_, E>
where
E: ShellInterface,
{
pub fn run(self) -> CommandResult<ExitStatus, StartError> {
self.environment.run_command(self.command)
}
pub fn output(self) -> CommandResult<CommandOutput, StartError> {
self.environment.collect_command_output(self.command)
}
pub fn run_logged(self, logger: &Logger) -> CommandResult<LoggedRunOutput, StartError>
where
Self: Sized,
{
match logger.level {
LogLevel::Debug | LogLevel::Info => {
let res = self.run();
CommandResult {
result: res.result.map(LoggedRunOutput::from),
command: res.command,
}
}
LogLevel::Error => {
let res = self.output();
CommandResult {
result: res.result.map(LoggedRunOutput::from),
command: res.command,
}
}
}
}
}
#[derive(Debug, Clone)]
pub enum ShellCommand {
Ssh {
@ -70,10 +38,12 @@ pub enum ShellCommand {
}
impl ShellCommand {
pub fn in_env<E>(self, environment: &mut E) -> EnvCommand<E> {
pub fn in_env<E>(self, _environment: &mut E) -> EnvCommand<E> {
EnvCommand {
command: self,
environment,
phantom_data: Default::default(),
#[cfg(test)]
environment: _environment,
}
}
}
@ -150,7 +120,8 @@ impl Display for ShellCommand {
}
}
fn command_to_string(command: &Command) -> String {
//TODO remove crate visibility once it isn't needed anymore
pub(crate) fn command_to_string(command: &Command) -> String {
once(command.get_program().to_string_lossy().to_string())
.chain(command.get_args().map(|arg| {
let arg_str = arg.to_string_lossy();
@ -173,7 +144,7 @@ macro_rules! cmd {
}};
}
pub fn build_command_from_shell_command(shell_command: &ShellCommand) -> Command {
fn build_command_from_shell_command(shell_command: &ShellCommand) -> Command {
match shell_command {
ShellCommand::Ssh {
address,
@ -220,11 +191,51 @@ pub fn build_command_from_shell_command(shell_command: &ShellCommand) -> Command
}
pub trait ShellInterface {
fn run_command(&mut self, command: ShellCommand) -> CommandResult<ExitStatus, StartError>;
fn collect_command_output(
&mut self,
command: ShellCommand,
) -> CommandResult<CommandOutput, StartError>;
fn run(self) -> CommandResult<ExitStatus, StartError>;
fn output(self) -> CommandResult<CommandOutput, StartError>;
fn run_logged(self, logger: &Logger) -> CommandResult<LoggedRunOutput, StartError>
where
Self: Sized,
{
match logger.level {
LogLevel::Debug | LogLevel::Info => {
let res = self.run();
CommandResult {
result: res.result.map(LoggedRunOutput::from),
command: res.command,
}
}
LogLevel::Error => {
let res = self.output();
CommandResult {
result: res.result.map(LoggedRunOutput::from),
command: res.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> {