Don't use shell command on local machine
This commit is contained in:
parent
0109bf6c6f
commit
faf4e47cac
@ -2,6 +2,7 @@ use std::error::Error;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::path::PathBuf;
|
||||
|
||||
//TODO this whole structure should probably use OsString instead of String
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct FileNameInfo {
|
||||
pub name: String,
|
||||
@ -82,6 +83,7 @@ impl Display for FileInfoError {
|
||||
|
||||
impl Error for FileInfoError {}
|
||||
|
||||
//TODO this structure should probably work with OsString instead of String
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FileMatcher {
|
||||
name: String,
|
||||
@ -108,7 +110,7 @@ impl FileMatcher {
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn matches(&self, file_name: &str) -> bool {
|
||||
file_name.starts_with(&self.name)
|
||||
&& self
|
||||
|
||||
99
src/main.rs
99
src/main.rs
@ -15,7 +15,7 @@ use clap::{Parser, Subcommand, ValueEnum};
|
||||
use lazy_regex::{lazy_regex, Lazy, Regex};
|
||||
use server::{Server, ServerReference};
|
||||
use std::cell::LazyCell;
|
||||
use std::ffi::OsStr;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::hash::Hash;
|
||||
use std::io::Write;
|
||||
use std::iter::once;
|
||||
@ -292,23 +292,35 @@ fn main() -> Result<(), String> {
|
||||
Ok(ServerActions {
|
||||
server,
|
||||
actions: {
|
||||
let mut ls_command = match &server.address {
|
||||
ServerAddress::Ssh { ssh_address } => {
|
||||
let mut cmd = ShellCmd::new("ssh");
|
||||
cmd.arg(ssh_address).arg(osf!("ls ") + &working_directory);
|
||||
cmd
|
||||
}
|
||||
ServerAddress::Localhost => {
|
||||
//TODO don't use shell command on localhost, this will fail on windows
|
||||
let mut cmd = ShellCmd::new("ls");
|
||||
cmd.arg(&working_directory);
|
||||
cmd
|
||||
}
|
||||
let present_file_names: Vec<OsString> = match &server.address {
|
||||
ServerAddress::Ssh { ssh_address } => ShellCmd::new("ls")
|
||||
.arg(ssh_address)
|
||||
.arg(osf!("ls ") + &working_directory)
|
||||
.collect_output()
|
||||
.map_err(|e| {
|
||||
format!(
|
||||
"Failed to query present files on server {}: {e}",
|
||||
server.get_name()
|
||||
)
|
||||
})?
|
||||
.stdout
|
||||
.split(|&b| b == b'\n')
|
||||
.map(|bytes| OsStr::from_bytes(bytes).to_os_string())
|
||||
.collect(),
|
||||
ServerAddress::Localhost => fs::read_dir(&working_directory)
|
||||
.map_err(|e| format!("Failed to get files in working directory: {e}"))?
|
||||
.map(|entry| entry.map_err(|e| format!("Failed to access directory entry: {e}")))
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.into_iter()
|
||||
.filter_map(|entry| {
|
||||
if entry.path().is_file() {
|
||||
Some(entry.file_name())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
let ls_output = ls_command
|
||||
.collect_output()
|
||||
.map_err(|e| format!("failed to query files: {e}"))?;
|
||||
let ls_output = String::from_utf8_lossy(&ls_output.stdout);
|
||||
|
||||
file_details
|
||||
.iter()
|
||||
@ -319,43 +331,56 @@ fn main() -> Result<(), String> {
|
||||
file_matcher = file_matcher.and_extension(extension);
|
||||
}
|
||||
|
||||
let file_name = file_name_info.to_full_file_name();
|
||||
let file_name = OsString::from(file_name_info.to_full_file_name());
|
||||
|
||||
let add_action = FileAction::new(file, Action::Add).expect("path points to file");
|
||||
|
||||
let mut ls_lines = ls_output.lines();
|
||||
|
||||
if pure && ls_lines.clone().any(|file| file == file_name) {
|
||||
log!(logger, debug, "file is already present on {}: {}", server.get_name(), file_name);
|
||||
if pure && present_file_names.iter().any(|file| *file == file_name) {
|
||||
log!(
|
||||
logger,
|
||||
debug,
|
||||
"file is already present on {}: {}",
|
||||
server.get_name(),
|
||||
file_name.to_string_lossy()
|
||||
);
|
||||
return vec![]; //ignore that file, since it is already present
|
||||
}
|
||||
|
||||
match old_version_policy {
|
||||
OldVersionPolicy::Ignore => {
|
||||
if !ls_lines.any(|file| file == file_name) {
|
||||
if !present_file_names.iter().any(|file| *file == file_name) {
|
||||
vec![add_action] //file doesn't exist yet
|
||||
} else {
|
||||
vec![FileAction::new(&file_name, Action::Replace)
|
||||
.expect("path points to file")]
|
||||
}
|
||||
}
|
||||
OldVersionPolicy::Archive => ls_lines
|
||||
.filter(|file| file_matcher.matches(file))
|
||||
.map(|file| {
|
||||
FileAction::new(
|
||||
file,
|
||||
Action::rename(format!("{file}{}", file.chars().last().unwrap_or('1'))),
|
||||
)
|
||||
.expect("path points to file")
|
||||
})
|
||||
.chain(once(add_action))
|
||||
.collect(),
|
||||
OldVersionPolicy::Archive => {
|
||||
//TODO avoid lossy match
|
||||
present_file_names
|
||||
.iter()
|
||||
.filter(|file| file_matcher.matches(&file.to_string_lossy()))
|
||||
.map(|file| {
|
||||
FileAction::new(
|
||||
file,
|
||||
Action::rename(format!(
|
||||
"{}{}",
|
||||
file.to_string_lossy(),
|
||||
file.to_string_lossy().chars().last().unwrap_or('1')
|
||||
)),
|
||||
)
|
||||
.expect("path points to file")
|
||||
})
|
||||
.chain(once(add_action))
|
||||
.collect()
|
||||
},
|
||||
OldVersionPolicy::Delete => {
|
||||
let mut actions = ls_lines
|
||||
.filter(|file| file_matcher.matches(file))
|
||||
//TODO avoid lossy match
|
||||
let mut actions = present_file_names.iter()
|
||||
.filter(|file| file_matcher.matches(&file.to_string_lossy()))
|
||||
.map(|file| {
|
||||
//special case -> file has the same name as current file, then we just need to replace it
|
||||
if file == file_name {
|
||||
if *file == file_name {
|
||||
FileAction::new(file, Action::Replace).expect("path points to file")
|
||||
} else {
|
||||
FileAction::new(file, Action::Delete).expect("path points to file")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user