From 0789b23c6c8e21bc1493455beaca75d46e0aa575 Mon Sep 17 00:00:00 2001 From: TD-Sky Date: Fri, 4 Aug 2023 20:02:23 +0800 Subject: [PATCH] feat(purge_all): allow passing in items' ownership or reference --- src/freedesktop.rs | 6 ++++-- src/lib.rs | 24 ++++++++++++++++++++++-- src/tests.rs | 13 ++++++------- src/windows.rs | 6 ++++-- 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/freedesktop.rs b/src/freedesktop.rs index 5d19991..19b41b7 100644 --- a/src/freedesktop.rs +++ b/src/freedesktop.rs @@ -7,6 +7,7 @@ //! use std::{ + borrow::Borrow, collections::HashSet, fs::{create_dir_all, File, OpenOptions}, io::{BufRead, BufReader, Write}, @@ -225,12 +226,13 @@ fn virtually_exists(path: &Path) -> std::io::Result { pub fn purge_all(items: I) -> Result<(), Error> where - I: IntoIterator, + I: IntoIterator, + ::Item: Borrow, { for item in items.into_iter() { // When purging an item the "in-trash" filename must be parsed from the trashinfo filename // which is the filename in the `id` field. - let info_file = &item.id; + let info_file = &item.borrow().id; // A bunch of unwraps here. This is fine because if any of these fail that means // that either there's a bug in this code or the target system didn't follow diff --git a/src/lib.rs b/src/lib.rs index 8bab380..73c33ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -305,6 +305,7 @@ pub mod os_limited { //! Linux or other Freedesktop Trash compliant environment. use std::{ + borrow::Borrow, collections::HashSet, hash::{Hash, Hasher}, }; @@ -332,10 +333,13 @@ pub mod os_limited { /// /// # Example /// + /// Taking items' ownership: + /// /// ``` /// use std::fs::File; /// use trash::{delete, os_limited::{list, purge_all}}; - /// let filename = "trash-purge_all-example"; + /// + /// let filename = "trash-purge_all-example-ownership"; /// File::create(filename).unwrap(); /// delete(filename).unwrap(); /// // Collect the filtered list just so that we can make sure there's exactly one element. @@ -344,9 +348,25 @@ pub mod os_limited { /// assert_eq!(selected.len(), 1); /// purge_all(selected).unwrap(); /// ``` + /// + /// Taking items' reference: + /// + /// ``` + /// use std::fs::File; + /// use trash::{delete, os_limited::{list, purge_all}}; + /// + /// let filename = "trash-purge_all-example-reference"; + /// File::create(filename).unwrap(); + /// delete(filename).unwrap(); + /// let mut selected = list().unwrap(); + /// selected.retain(|x| x.name == filename); + /// assert_eq!(selected.len(), 1); + /// purge_all(&selected).unwrap(); + /// ``` pub fn purge_all(items: I) -> Result<(), Error> where - I: IntoIterator, + I: IntoIterator, + ::Item: Borrow, { platform::purge_all(items) } diff --git a/src/tests.rs b/src/tests.rs index 2fae2ab..3a1427f 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -88,13 +88,13 @@ mod os_limited { // Let's try to purge all the items we just created but ignore any errors // as this test should succeed as long as `list` works properly. - let _ = trash::os_limited::purge_all(items.into_iter().map(|(_name, item)| item).flatten()); + let _ = trash::os_limited::purge_all(items.iter().flat_map(|(_name, item)| item)); } #[test] fn purge_empty() { init_logging(); - trash::os_limited::purge_all(vec![]).unwrap(); + trash::os_limited::purge_all::>(vec![]).unwrap(); } #[test] @@ -182,8 +182,7 @@ mod os_limited { trash::os_limited::list().unwrap().into_iter().filter(|x| x.name.starts_with(&file_name_prefix)).collect(); targets.sort_by(|a, b| a.name.cmp(&b.name)); assert_eq!(targets.len(), file_count); - let remaining_count; - match trash::os_limited::restore_all(targets) { + let remaining_count = match trash::os_limited::restore_all(targets) { Err(trash::Error::RestoreCollision { remaining_items, .. }) => { let contains = |v: &Vec, name: &String| { for curr in v.iter() { @@ -197,7 +196,7 @@ mod os_limited { for path in names.iter().filter(|filename| !contains(&remaining_items, filename)) { assert!(File::open(path).is_ok()); } - remaining_count = remaining_items.len(); + remaining_items.len() } _ => { for path in names.iter() { @@ -205,7 +204,7 @@ mod os_limited { } panic!("restore_all was expected to return `trash::ErrorKind::RestoreCollision` but did not."); } - } + }; let remaining = trash::os_limited::list() .unwrap() .into_iter() @@ -233,7 +232,7 @@ mod os_limited { let twin_name = &names[1]; File::create(twin_name).unwrap(); - trash::delete(&twin_name).unwrap(); + trash::delete(twin_name).unwrap(); let mut targets: Vec<_> = trash::os_limited::list().unwrap().into_iter().filter(|x| x.name.starts_with(&file_name_prefix)).collect(); diff --git a/src/windows.rs b/src/windows.rs index 88e1178..e617647 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -1,5 +1,6 @@ use crate::{Error, TrashContext, TrashItem}; use std::{ + borrow::Borrow, ffi::{c_void, OsStr, OsString}, fs, os::windows::{ffi::OsStrExt, prelude::*}, @@ -125,7 +126,8 @@ pub fn list() -> Result, Error> { pub fn purge_all(items: I) -> Result<(), Error> where - I: IntoIterator, + I: IntoIterator, + ::Item: Borrow, { ensure_com_initialized(); unsafe { @@ -134,7 +136,7 @@ where let mut at_least_one = false; for item in items { at_least_one = true; - let id_as_wide: Vec = item.id.encode_wide().chain(std::iter::once(0)).collect(); + let id_as_wide: Vec = item.borrow().id.encode_wide().chain(std::iter::once(0)).collect(); let parsing_name = PCWSTR(id_as_wide.as_ptr()); let trash_item: IShellItem = SHCreateItemFromParsingName(parsing_name, None)?; pfo.DeleteItem(&trash_item, None)?;