Canonicalize files to upload if they are on remote server

This commit is contained in:
Leonard Steppy 2025-02-03 01:47:36 +01:00
parent 329ba8f381
commit 6e4a23254a
2 changed files with 40 additions and 6 deletions

View File

@ -15,9 +15,11 @@ 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};
use std::cell::LazyCell; use std::cell::LazyCell;
use std::ffi::{OsStr, 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;
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::str::FromStr; use std::str::FromStr;
use std::{env, fs, io}; use std::{env, fs, io};
@ -178,7 +180,7 @@ fn main() -> Result<(), String> {
match args.command { match args.command {
Command::Upload { Command::Upload {
files, mut files,
file_server, file_server,
old_version_policy, old_version_policy,
mut upload_directory, mut upload_directory,
@ -186,6 +188,7 @@ fn main() -> Result<(), String> {
file_name, file_name,
} => { } => {
require_non_empty_servers(&servers)?; require_non_empty_servers(&servers)?;
require_non_empty(&files, "files to upload")?;
start_ssh_agent(&logger)?; start_ssh_agent(&logger)?;
//resolve file server //resolve file server
@ -204,6 +207,25 @@ fn main() -> Result<(), String> {
match &file_server { match &file_server {
Some(file_server) => match &file_server.address { Some(file_server) => match &file_server.address {
ServerAddress::Ssh { ssh_address } => { ServerAddress::Ssh { ssh_address } => {
//canonicalize remote files
let joined_files = osf!("{{")
+ files
.iter()
.map(|file| file.as_os_str())
.collect::<Vec<_>>()
.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 { for file in &files {
check_file_exists_on_server(file, ssh_address, &file_server.server_directory_path)?; check_file_exists_on_server(file, ssh_address, &file_server.server_directory_path)?;
} }
@ -580,12 +602,17 @@ fn get_home_directory() -> Result<PathBuf, String> {
.and_then(|home_dir| home_dir.ok_or("Failed to find home directory".to_string())) .and_then(|home_dir| home_dir.ok_or("Failed to find home directory".to_string()))
} }
fn require_non_empty_servers(servers: &[Server]) -> Result<(), String> { fn require_non_empty_servers<T>(servers: &[T]) -> Result<(), String> {
if servers.is_empty() { require_non_empty(servers, "servers for this operation")
Err("You did not provide any servers for this operation. Please see --help".to_string()) }
} else {
Ok(()) fn require_non_empty<T>(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> { fn start_ssh_agent(logger: &Logger) -> Result<(), String> {

View File

@ -2,6 +2,7 @@ use std::ffi::{OsStr, OsString};
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::ops::{Add, AddAssign}; use std::ops::{Add, AddAssign};
use std::path::Path;
pub trait ReplaceWithOsStr<'a, Pattern = &'a str> { pub trait ReplaceWithOsStr<'a, Pattern = &'a str> {
#[must_use] #[must_use]
@ -56,6 +57,12 @@ impl AsRef<OsStr> for OsStringBuilder {
} }
} }
impl AsRef<Path> for OsStringBuilder {
fn as_ref(&self) -> &Path {
self.result.as_ref()
}
}
impl<P> Add<P> for OsStringBuilder impl<P> Add<P> for OsStringBuilder
where where
P: AsRef<OsStr>, P: AsRef<OsStr>,