Skip to content

Commit

Permalink
Return trash items that are created by delete
Browse files Browse the repository at this point in the history
  • Loading branch information
jackpot51 committed Jul 11, 2024
1 parent a754f4a commit f7aef11
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 22 deletions.
29 changes: 20 additions & 9 deletions src/freedesktop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,13 @@ impl PlatformTrashContext {
}
}
impl TrashContext {
pub(crate) fn delete_all_canonicalized(&self, full_paths: Vec<PathBuf>) -> Result<(), Error> {
pub(crate) fn delete_all_canonicalized(&self, full_paths: Vec<PathBuf>) -> Result<Option<Vec<TrashItem>>, Error> {
let home_trash = home_trash()?;
let sorted_mount_points = get_sorted_mount_points()?;
let home_topdir = home_topdir(&sorted_mount_points)?;
debug!("The home topdir is {:?}", home_topdir);
let uid = unsafe { libc::getuid() };
let mut items = Vec::with_capacity(full_paths.len());
for path in full_paths {
debug!("Deleting {:?}", path);
let topdir = get_first_topdir_containing_path(&path, &sorted_mount_points);
Expand All @@ -47,15 +48,16 @@ impl TrashContext {
debug!("The topdir was identical to the home topdir, so moving to the home trash.");
// Note that the following function creates the trash folder
// and its required subfolders in case they don't exist.
move_to_trash(path, &home_trash, topdir).map_err(|(p, e)| fs_error(p, e))?;
items.push(move_to_trash(path, &home_trash, topdir).map_err(|(p, e)| fs_error(p, e))?);
} else {
execute_on_mounted_trash_folders(uid, topdir, true, true, |trash_path| {
move_to_trash(&path, trash_path, topdir)
items.push(move_to_trash(&path, trash_path, topdir)?);
Ok(())
})
.map_err(|(p, e)| fs_error(p, e))?;
.map_err(|(p, e)| fs_error(p, e))?
}
}
Ok(())
Ok(Some(items))
}
}

Expand Down Expand Up @@ -421,7 +423,7 @@ fn move_to_trash(
src: impl AsRef<Path>,
trash_folder: impl AsRef<Path>,
_topdir: impl AsRef<Path>,
) -> Result<(), FsError> {
) -> Result<TrashItem, FsError> {
let src = src.as_ref();
let trash_folder = trash_folder.as_ref();
let files_folder = trash_folder.join("files");
Expand Down Expand Up @@ -462,6 +464,7 @@ fn move_to_trash(
info_name.push(".trashinfo");
let info_file_path = info_folder.join(&info_name);
let info_result = OpenOptions::new().create_new(true).write(true).open(&info_file_path);
let mut time_deleted = -1;
match info_result {
Err(error) => {
if error.kind() == std::io::ErrorKind::AlreadyExists {
Expand All @@ -481,10 +484,12 @@ fn move_to_trash(
#[cfg(feature = "chrono")]
{
let now = chrono::Local::now();
time_deleted = now.timestamp();
writeln!(file, "DeletionDate={}", now.format("%Y-%m-%dT%H:%M:%S"))
}
#[cfg(not(feature = "chrono"))]
{
time_deleted = -1;
Ok(())
}
})
Expand All @@ -508,12 +513,18 @@ fn move_to_trash(
}
Ok(_) => {
// We did it!
break;
return Ok(TrashItem {
id: info_file_path.into(),
name: filename.into(),
original_parent: src
.parent()
.expect("Absolute path to trashed item should have a parent")
.to_path_buf(),
time_deleted,
});
}
}
}

Ok(())
}

fn execute_src_to_dst_operation<S1, D1>(
Expand Down
8 changes: 4 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl TrashContext {
/// trash::delete("delete_me").unwrap();
/// assert!(File::open("delete_me").is_err());
/// ```
pub fn delete<T: AsRef<Path>>(&self, path: T) -> Result<(), Error> {
pub fn delete<T: AsRef<Path>>(&self, path: T) -> Result<Option<Vec<TrashItem>>, Error> {
self.delete_all(&[path])
}

Expand All @@ -101,7 +101,7 @@ impl TrashContext {
/// assert!(File::open("delete_me_1").is_err());
/// assert!(File::open("delete_me_2").is_err());
/// ```
pub fn delete_all<I, T>(&self, paths: I) -> Result<(), Error>
pub fn delete_all<I, T>(&self, paths: I) -> Result<Option<Vec<TrashItem>>, Error>
where
I: IntoIterator<Item = T>,
T: AsRef<Path>,
Expand All @@ -116,14 +116,14 @@ impl TrashContext {
/// Convenience method for `DEFAULT_TRASH_CTX.delete()`.
///
/// See: [`TrashContext::delete`](TrashContext::delete)
pub fn delete<T: AsRef<Path>>(path: T) -> Result<(), Error> {
pub fn delete<T: AsRef<Path>>(path: T) -> Result<Option<Vec<TrashItem>>, Error> {
DEFAULT_TRASH_CTX.delete(path)
}

/// Convenience method for `DEFAULT_TRASH_CTX.delete_all()`.
///
/// See: [`TrashContext::delete_all`](TrashContext::delete_all)
pub fn delete_all<I, T>(paths: I) -> Result<(), Error>
pub fn delete_all<I, T>(paths: I) -> Result<Option<Vec<TrashItem>>, Error>
where
I: IntoIterator<Item = T>,
T: AsRef<Path>,
Expand Down
9 changes: 5 additions & 4 deletions src/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{ffi::OsString, path::PathBuf, process::Command};
use log::trace;
use objc2_foundation::{NSFileManager, NSString, NSURL};

use crate::{into_unknown, Error, TrashContext};
use crate::{into_unknown, Error, TrashContext, TrashItem};

#[derive(Copy, Clone, Debug)]
pub enum DeleteMethod {
Expand Down Expand Up @@ -61,12 +61,13 @@ impl TrashContextExtMacos for TrashContext {
}
}
impl TrashContext {
pub(crate) fn delete_all_canonicalized(&self, full_paths: Vec<PathBuf>) -> Result<(), Error> {
pub(crate) fn delete_all_canonicalized(&self, full_paths: Vec<PathBuf>) -> Result<Option<Vec<TrashItem>>, Error> {
let full_paths = full_paths.into_iter().map(to_string).collect::<Result<Vec<_>, _>>()?;
match self.platform_specific.delete_method {
DeleteMethod::Finder => delete_using_finder(full_paths),
DeleteMethod::NsFileManager => delete_using_file_mgr(full_paths),
DeleteMethod::Finder => delete_using_finder(full_paths)?,
DeleteMethod::NsFileManager => delete_using_file_mgr(full_paths)?,
}
Ok(None)
}
}

Expand Down
12 changes: 7 additions & 5 deletions src/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ impl PlatformTrashContext {
}
impl TrashContext {
/// See https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-_shfileopstructa
pub(crate) fn delete_specified_canonicalized(&self, full_paths: Vec<PathBuf>) -> Result<(), Error> {
pub(crate) fn delete_specified_canonicalized(
&self,
full_paths: Vec<PathBuf>,
) -> Result<Option<Vec<TrashItem>>, Error> {
ensure_com_initialized();
unsafe {
let pfo: IFileOperation = CoCreateInstance(&FileOperation as *const _, None, CLSCTX_ALL).unwrap();
Expand All @@ -57,14 +60,13 @@ impl TrashContext {
pfo.DeleteItem(&shi, None)?;
}
pfo.PerformOperations()?;
Ok(())
Ok(None)
}
}

/// Removes all files and folder paths recursively.
pub(crate) fn delete_all_canonicalized(&self, full_paths: Vec<PathBuf>) -> Result<(), Error> {
self.delete_specified_canonicalized(full_paths)?;
Ok(())
pub(crate) fn delete_all_canonicalized(&self, full_paths: Vec<PathBuf>) -> Result<Option<Vec<TrashItem>>, Error> {
self.delete_specified_canonicalized(full_paths)
}
}

Expand Down

0 comments on commit f7aef11

Please sign in to comment.