Add OsStringBuilder and remove debug usages

This commit is contained in:
Leonard Steppy 2024-12-13 12:50:05 +01:00
parent 28bdcb41aa
commit 435c87c958
2 changed files with 152 additions and 31 deletions

View File

@ -1,5 +1,6 @@
mod action; mod action;
mod file; mod file;
mod os_string_builder;
mod server; mod server;
use crate::action::{Action, FileAction, ServerActions}; use crate::action::{Action, FileAction, ServerActions};
@ -9,7 +10,6 @@ use lazy_regex::{lazy_regex, Lazy, Regex};
use server::{Server, ServerReference}; use server::{Server, ServerReference};
use std::cell::LazyCell; use std::cell::LazyCell;
use std::env; use std::env;
use std::ffi::OsString;
use std::hash::Hash; use std::hash::Hash;
use std::io::Write; use std::io::Write;
use std::iter::once; use std::iter::once;
@ -119,13 +119,9 @@ fn main() -> Result<(), String> {
Ok(ServerActions { Ok(ServerActions {
server, server,
actions: { actions: {
//TODO don't use debug values here, use joiner
let output = ShellCmd::new("ssh") let output = ShellCmd::new("ssh")
.arg(&server.ssh_name) .arg(&server.ssh_name)
.arg(format!( .arg(osf!("ls ") + server.server_directory_path.join(&upload_directory))
"cd {:?}; ls {:?}",
server.server_directory_path, upload_directory
))
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.output() .output()
.map_err(|e| format!("failed to query files via ssh: {e}"))?; .map_err(|e| format!("failed to query files via ssh: {e}"))?;
@ -206,47 +202,43 @@ fn main() -> Result<(), String> {
for file_action in server_actions.actions { for file_action in server_actions.actions {
match file_action.kind { match file_action.kind {
Action::Add | Action::Replace => { Action::Add | Action::Replace => {
//TODO replace with joiner
let mut destination = OsString::from(&server.ssh_name);
destination.push(":");
destination.push(&server.server_directory_path);
if !server
.server_directory_path
.to_string_lossy()
.ends_with("/")
{
destination.push("/");
}
destination.push(&upload_directory);
ShellCmd::new("scp") ShellCmd::new("scp")
.arg(file.clone()) .arg(file.clone())
.arg(destination) .arg(
osf!(&server.ssh_name)
+ ":"
+ server.server_directory_path.join(&upload_directory),
)
.spawn() .spawn()
.map_err(|e| format!("failed to upload file: {e}"))? .map_err(|e| format!("failed to upload file: {e}"))?
.wait() .wait()
.map_err(|e| format!("failed to wait for upload: {e}"))?; .map_err(|e| format!("failed to wait for upload: {e}"))?;
} }
Action::Delete => { Action::Delete => {
//TODO don't use debug values here, use joiner
ShellCmd::new("ssh") ShellCmd::new("ssh")
.arg(&server.ssh_name) .arg(&server.ssh_name)
.arg(format!( .arg(
"cd {:?}; cd {upload_directory:?}; rm {:?}", osf!("cd ")
server.server_directory_path, file_action.file + server.server_directory_path.join(&upload_directory)
)) + "; rm "
+ &file_action.file,
)
.spawn() .spawn()
.map_err(|e| format!("failed to send delete command: {e}"))? .map_err(|e| format!("failed to send delete command: {e}"))?
.wait() .wait()
.map_err(|e| format!("failed to wait for delete command: {e}"))?; .map_err(|e| format!("failed to wait for delete command: {e}"))?;
} }
Action::Rename { new_name } => { Action::Rename { new_name } => {
//TODO don't use debug values, use joiner
ShellCmd::new("ssh") ShellCmd::new("ssh")
.arg(&server.ssh_name) .arg(&server.ssh_name)
.arg(format!( .arg(
"cd {:?}; cd {upload_directory:?}; mv {:?} {new_name:?}", osf!("cd ")
server.server_directory_path, file_action.file + server.server_directory_path.join(&upload_directory)
)) + "; mv "
+ &file_action.file
+ " "
+ new_name,
)
.spawn() .spawn()
.map_err(|e| format!("failed to send rename command: {e}"))? .map_err(|e| format!("failed to send rename command: {e}"))?
.wait() .wait()
@ -262,10 +254,9 @@ fn main() -> Result<(), String> {
start_ssh_agent()?; start_ssh_agent()?;
for server in servers { for server in servers {
println!("Running command on '{}'...", server.ssh_name); println!("Running command on '{}'...", server.ssh_name);
//TODO don't use debug values, use joiner
ShellCmd::new("ssh") ShellCmd::new("ssh")
.arg(server.ssh_name) .arg(server.ssh_name)
.arg(format!("cd {:?}; {command}", server.server_directory_path)) .arg(osf!("cd ") + server.server_directory_path + "; " + &command)
.spawn() .spawn()
.map_err(|_| "failed to start ssh command".to_string())? .map_err(|_| "failed to start ssh command".to_string())?
.wait() .wait()
@ -343,4 +334,13 @@ mod test {
servers servers
); );
} }
#[test]
fn path_experiment() {
let server_dir = PathBuf::from("steptech");
let upload_dir = PathBuf::from("/home"); //absolute path
let joined = server_dir.join(upload_dir);
assert_eq!(PathBuf::from("/home"), joined);
}
} }

121
src/os_string_builder.rs Normal file
View File

@ -0,0 +1,121 @@
use std::ffi::{OsStr, OsString};
use std::fmt::{Debug, Formatter};
use std::hash::{Hash, Hasher};
use std::ops::{Add, AddAssign};
use std::os::unix::ffi::OsStrExt;
#[derive(Clone, Default, Eq)]
pub struct OsStringBuilder {
result: OsString,
}
impl OsStringBuilder {
pub fn from(s: impl AsRef<OsStr>) -> Self {
Self {
result: s.as_ref().to_os_string(),
}
}
pub fn build(&self) -> OsString {
self.result.clone()
}
}
impl From<OsStringBuilder> for OsString {
fn from(value: OsStringBuilder) -> Self {
value.result
}
}
impl Debug for OsStringBuilder {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Debug::fmt(&self.result, f)
}
}
impl AsRef<OsStr> for OsStringBuilder {
fn as_ref(&self) -> &OsStr {
self.result.as_ref()
}
}
impl<P> Add<P> for OsStringBuilder
where
P: AsRef<OsStr>,
{
type Output = Self;
fn add(mut self, rhs: P) -> Self::Output {
self.result.push(rhs);
self
}
}
impl<P> AddAssign<P> for OsStringBuilder
where
P: AsRef<OsStr>,
{
fn add_assign(&mut self, rhs: P) {
self.result.push(rhs);
}
}
impl<P> PartialEq<P> for OsStringBuilder
where
P: AsRef<OsStr>,
{
fn eq(&self, other: &P) -> bool {
self.result == other.as_ref()
}
}
impl Hash for OsStringBuilder {
fn hash<H: Hasher>(&self, state: &mut H) {
self.result.hash(state);
}
}
pub fn ensure_trailing_slash(path: impl AsRef<OsStr>) -> OsString {
let mut str = path.as_ref().to_os_string();
if !str.as_bytes().ends_with(b"/") {
str.push("/")
}
str
}
#[macro_export]
macro_rules! dir {
($path:expr) => {{
use $crate::os_string_builder::ensure_trailing_slash;
ensure_trailing_slash($path)
}};
}
#[macro_export]
macro_rules! osf {
() => {{
use $crate::os_string_builder::OsStringBuilder;
OsStringBuilder::default()
}};
($s:expr) => {
osf!() + $s
};
}
#[cfg(test)]
mod test {
use std::path::PathBuf;
#[test]
fn test_build() {
assert_eq!(osf!("foo") + "Bar", "fooBar");
}
#[test]
fn test_add_dir() {
let foo = PathBuf::from("foo");
let bar = PathBuf::from("bar");
assert_eq!(osf!("cd ") + dir!(foo) + dir!(bar), "cd foo/bar/");
}
}