Skip to content

Commit

Permalink
fmt
Browse files Browse the repository at this point in the history
  • Loading branch information
eugenesvk committed Dec 6, 2024
1 parent ac1bc98 commit ab7ca81
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 55 deletions.
125 changes: 76 additions & 49 deletions src/macos.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use std::{
path::{Path, PathBuf},
};
use std::path::{Path, PathBuf};

use log::{trace, warn};
use objc2::rc::Retained;
Expand Down Expand Up @@ -155,10 +153,13 @@ fn delete_using_file_mgr<P: AsRef<Path>>(full_paths: &[P], with_info: bool) -> R
}
}

fn delete_using_finder<P: AsRef<Path> + std::fmt::Debug>(full_paths: &[P], with_info: bool) -> Result<Option<Vec<TrashItem>>, Error> {
fn delete_using_finder<P: AsRef<Path> + std::fmt::Debug>(
full_paths: &[P],
with_info: bool,
) -> Result<Option<Vec<TrashItem>>, Error> {
// TODO: should we convert to trashing item by item instead of in batches to have a guaranteed match of input to output?
// which method is faster?
// what about with a lot of items? will a huge script combining all paths still work?
// which method is faster?
// what about with a lot of items? will a huge script combining all paths still work?
use osakit::{Language, Script};
let mut items: Vec<TrashItem> = if with_info { Vec::with_capacity(full_paths.len()) } else { vec![] };
let posix_files = full_paths
Expand All @@ -172,7 +173,9 @@ fn delete_using_finder<P: AsRef<Path> + std::fmt::Debug>(full_paths: &[P], with_
})
.collect::<Vec<String>>()
.join(", ");
let script_text = if with_info { format!(r#"
let script_text = if with_info {
format!(
r#"
tell application "Finder"
set Trash_items to delete {{ {posix_files} }}
end tell
Expand All @@ -183,56 +186,80 @@ fn delete_using_finder<P: AsRef<Path> + std::fmt::Debug>(full_paths: &[P], with_
set contents of aFile to (POSIX path of (aFile as alias)) -- can't get paths of Finder reference, coersion to alias needed
end repeat
return Trash_items
"#)
} else {format!(r#"tell application "Finder" to delete {{ {posix_files} }}"#)};
"#
)
} else {
format!(r#"tell application "Finder" to delete {{ {posix_files} }}"#)
};
let mut script = Script::new_from_source(Language::AppleScript, &script_text);

// Compile and Execute script
match script.compile() {
Ok(_) => match script.execute() {
Ok(res) => { if with_info {
#[allow(unused_assignments)]
let mut time_deleted = -1;
#[cfg(feature = "chrono")]
{
let now = chrono::Local::now();
time_deleted = now.timestamp();
}
#[cfg(not(feature = "chrono"))]
{
time_deleted = -1;
}
let res_arr = if let Some(file_path) = res.as_str() { // convert a single value into an array for ease of handling later
vec![file_path].into()
} else {res};
if let Some(file_list) = res_arr.as_array() {
let len_match = full_paths.len()==file_list.len();
if ! len_match {warn!("AppleScript returned a list of trashed paths len {} ≠ {} expected items sent to be trashed, to trashed items will have empty names/original parents as we cant be certain which trash path matches which trashed item",full_paths.len(),file_list.len());}
for (i,posix_path) in file_list.iter().enumerate() {
if let Some(file_path) = posix_path.as_str() { // Finder's return paths should be utf8 (%-encoded?)?
//let p=PathBuf::from(file_path);
//println!("✓converted posix_path:{}
// \nexists {} {:?}", posix_path, p.exists(),p);
let path_r = if len_match {full_paths[i].as_ref()} else {Path::new("")};
items.push(TrashItem {
id: file_path.into(),
name: if len_match {path_r.file_name().expect("Item to be trashed should have a name").into()
} else {"".into()},
original_parent: if len_match {path_r.parent().expect("Item to be trashed should have a parent").to_path_buf()
} else {"".into()},
time_deleted,
});
} else {warn!("Failed to parse AppleScript's returned path to the trashed file: {:?}",&posix_path);}
Ok(res) => {
if with_info {
#[allow(unused_assignments)]
let mut time_deleted = -1;
#[cfg(feature = "chrono")]
{
let now = chrono::Local::now();
time_deleted = now.timestamp();
}
#[cfg(not(feature = "chrono"))]
{
time_deleted = -1;
}
let res_arr = if let Some(file_path) = res.as_str() {
// convert a single value into an array for ease of handling later
vec![file_path].into()
} else {
res
};
if let Some(file_list) = res_arr.as_array() {
let len_match = full_paths.len() == file_list.len();
if !len_match {
warn!("AppleScript returned a list of trashed paths len {} ≠ {} expected items sent to be trashed, to trashed items will have empty names/original parents as we cant be certain which trash path matches which trashed item",full_paths.len(),file_list.len());
}
for (i, posix_path) in file_list.iter().enumerate() {
if let Some(file_path) = posix_path.as_str() {
// Finder's return paths should be utf8 (%-encoded?)?
//let p=PathBuf::from(file_path);
//println!("✓converted posix_path:{}
// \nexists {} {:?}", posix_path, p.exists(),p);
let path_r = if len_match { full_paths[i].as_ref() } else { Path::new("") };
items.push(TrashItem {
id: file_path.into(),
name: if len_match {
path_r.file_name().expect("Item to be trashed should have a name").into()
} else {
"".into()
},
original_parent: if len_match {
path_r.parent().expect("Item to be trashed should have a parent").to_path_buf()
} else {
"".into()
},
time_deleted,
});
} else {
warn!(
"Failed to parse AppleScript's returned path to the trashed file: {:?}",
&posix_path
);
}
}
return Ok(Some(items));
} else {
let ss = if full_paths.len() > 1 { "s" } else { "" };
warn!("AppleScript did not return a list of path{} to the trashed file{}, originally located at: {:?}",&ss,&ss,&full_paths);
}
return Ok(Some(items))
} else {
let ss = if full_paths.len() > 1 {"s"} else {""};
warn!("AppleScript did not return a list of path{} to the trashed file{}, originally located at: {:?}",&ss,&ss,&full_paths);
}
}},
Err(e) => return Err(Error::Unknown {description: format!("The AppleScript failed with error: {}", e),}),
}
Err(e) => return Err(Error::Unknown { description: format!("The AppleScript failed with error: {}", e) }),
},
Err(e) => return Err(Error::Unknown {description: format!("The AppleScript failed to compile with error: {}", e),}),
Err(e) => {
return Err(Error::Unknown { description: format!("The AppleScript failed to compile with error: {}", e) })
}
}
Ok(None)
}
Expand Down
11 changes: 5 additions & 6 deletions src/test_macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ fn test_delete_with_finder_with_info() {
path2.set_extension(r#"x80=%80 slash=\ pc=% quote=" comma=,"#);
File::create_new(&path1).unwrap();
File::create_new(&path2).unwrap();
let trashed_items = trash_ctx.delete_all_with_info(&[path1.clone(),path2.clone()]).unwrap().unwrap(); //Ok + Some trashed paths
let trashed_items = trash_ctx.delete_all_with_info(&[path1.clone(), path2.clone()]).unwrap().unwrap(); //Ok + Some trashed paths
assert!(File::open(&path1).is_err()); // original files deleted
assert!(File::open(&path2).is_err());
for item in trashed_items {
let trashed_path = item.id;
assert!(!File::open(&trashed_path).is_err()); // returned trash items exist
std::fs::remove_file(&trashed_path).unwrap(); // clean up
assert!( File::open(&trashed_path).is_err()); // cleaned up trash items
assert!(File::open(&trashed_path).is_err()); // cleaned up trash items
}

// test a single file (in case returned paths aren't an array anymore)
Expand All @@ -43,10 +43,9 @@ fn test_delete_with_finder_with_info() {
let trashed_path = item.id;
assert!(!File::open(&trashed_path).is_err()); // returned trash items exist
std::fs::remove_file(&trashed_path).unwrap(); // clean up
assert!( File::open(&trashed_path).is_err()); // cleaned up trash items
assert!(File::open(&trashed_path).is_err()); // cleaned up trash items
}


#[test]
#[serial]
fn test_delete_binary_with_finder_with_info() {
Expand All @@ -64,14 +63,14 @@ fn test_delete_binary_with_finder_with_info() {
File::create_new(&path2).unwrap();
assert!(&path1.exists());
assert!(&path2.exists());
let trashed_items = trash_ctx.delete_all_with_info(&[path1.clone(),path2.clone()]).unwrap().unwrap(); //Ok + Some trashed paths
let trashed_items = trash_ctx.delete_all_with_info(&[path1.clone(), path2.clone()]).unwrap().unwrap(); //Ok + Some trashed paths
assert!(File::open(&path1).is_err()); // original files deleted
assert!(File::open(&path2).is_err());
for item in trashed_items {
let trashed_path = item.id;
assert!(!File::open(&trashed_path).is_err()); // returned trash items exist
std::fs::remove_file(&trashed_path).unwrap(); // clean up
assert!( File::open(&trashed_path).is_err()); // cleaned up trash items
assert!(File::open(&trashed_path).is_err()); // cleaned up trash items
}
}

Expand Down

0 comments on commit ab7ca81

Please sign in to comment.