From 6e4a23254a737d0b7620ffaf39def02985691684 Mon Sep 17 00:00:00 2001 From: Steppy Date: Mon, 3 Feb 2025 01:47:36 +0100 Subject: [PATCH] Canonicalize files to upload if they are on remote server --- src/main.rs | 39 +++++++++++++++++++++++++++++++++------ src/os_string_builder.rs | 7 +++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index 72de303..aa6ec71 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,9 +15,11 @@ use clap::{Parser, Subcommand, ValueEnum}; use lazy_regex::{lazy_regex, Lazy, Regex}; use server::{Server, ServerReference}; use std::cell::LazyCell; +use std::ffi::{OsStr, OsString}; use std::hash::Hash; use std::io::Write; use std::iter::once; +use std::os::unix::ffi::OsStrExt; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::{env, fs, io}; @@ -178,7 +180,7 @@ fn main() -> Result<(), String> { match args.command { Command::Upload { - files, + mut files, file_server, old_version_policy, mut upload_directory, @@ -186,6 +188,7 @@ fn main() -> Result<(), String> { file_name, } => { require_non_empty_servers(&servers)?; + require_non_empty(&files, "files to upload")?; start_ssh_agent(&logger)?; //resolve file server @@ -204,6 +207,25 @@ fn main() -> Result<(), String> { match &file_server { Some(file_server) => match &file_server.address { ServerAddress::Ssh { ssh_address } => { + //canonicalize remote files + let joined_files = osf!("{{") + + files + .iter() + .map(|file| file.as_os_str()) + .collect::>() + .join(&OsString::from(",")) + + "}"; + let realpath_output = ShellCmd::new("ssh") + .arg(ssh_address) + .arg(osf!("realpath ") + file_server.server_directory_path.join(joined_files)) + .collect_output() + .map_err(|e| format!("failed to canonicalize files to upload: {e}"))?; + files = realpath_output + .stdout + .split(|&b| b == b'\n') //split at line breaks + .map(|bytes| PathBuf::from(OsStr::from_bytes(bytes))) + .collect(); + for file in &files { check_file_exists_on_server(file, ssh_address, &file_server.server_directory_path)?; } @@ -580,12 +602,17 @@ fn get_home_directory() -> Result { .and_then(|home_dir| home_dir.ok_or("Failed to find home directory".to_string())) } -fn require_non_empty_servers(servers: &[Server]) -> Result<(), String> { - if servers.is_empty() { - Err("You did not provide any servers for this operation. Please see --help".to_string()) - } else { - Ok(()) +fn require_non_empty_servers(servers: &[T]) -> Result<(), String> { + require_non_empty(servers, "servers for this operation") +} + +fn require_non_empty(slice: &[T], slice_name: &str) -> Result<(), String> { + if slice.is_empty() { + Err(format!( + "You did not provide any {slice_name}. Please see --help" + ))? } + Ok(()) } fn start_ssh_agent(logger: &Logger) -> Result<(), String> { diff --git a/src/os_string_builder.rs b/src/os_string_builder.rs index 0879e2c..f03e373 100644 --- a/src/os_string_builder.rs +++ b/src/os_string_builder.rs @@ -2,6 +2,7 @@ use std::ffi::{OsStr, OsString}; use std::fmt::{Debug, Formatter}; use std::hash::{Hash, Hasher}; use std::ops::{Add, AddAssign}; +use std::path::Path; pub trait ReplaceWithOsStr<'a, Pattern = &'a str> { #[must_use] @@ -56,6 +57,12 @@ impl AsRef for OsStringBuilder { } } +impl AsRef for OsStringBuilder { + fn as_ref(&self) -> &Path { + self.result.as_ref() + } +} + impl

Add

for OsStringBuilder where P: AsRef,