Skip to content

Commit

Permalink
Minor adjustments
Browse files Browse the repository at this point in the history
  • Loading branch information
ArturKovacs committed Apr 16, 2021
1 parent 32de332 commit 314e808
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 70 deletions.
102 changes: 52 additions & 50 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
//! [`restore_all`]: linux_windows/fn.restore_all.html
//!

use std::collections::HashSet;
use std::ffi::OsString;
use std::hash::{Hash, Hasher};
use std::path::{Path, PathBuf};
Expand All @@ -33,7 +32,7 @@ mod tests;
#[path = "windows.rs"]
mod platform;

#[cfg(target_os = "linux")]
#[cfg(all(unix, not(target_os = "macos")))]
#[path = "linux.rs"]
mod platform;

Expand Down Expand Up @@ -148,6 +147,7 @@ pub enum ErrorKind {
/// `std::io::Error` but this is not guaranteed.
///
/// `path`: The path to the file or folder on which this error occured.
// TODO: Add a description field
Filesystem { path: PathBuf },

/// This kind of error happens when a trash item's original parent already contains an item with
Expand All @@ -163,16 +163,57 @@ pub enum ErrorKind {
/// `path`: The path of the file that's blocking the trash item from being restored.
/// `remaining_items`: All items that were not restored in the order they were provided,
/// starting with the item that triggered the error.
// TODO: Rework this error such that all files are restored which can be restored,
// and only the ones that collide, are returned.
RestoreCollision { path: PathBuf, remaining_items: Vec<TrashItem> },

/// This sort of error is returned when multiple items with the same `original_path` were
/// requested to be restored. These items are referred to as twins here.
/// requested to be restored. These items are referred to as twins here. If there are twins
/// among the items, then none of the items are restored.
///
/// `path`: The `original_path` of the twins.
/// `items`: The complete list of items that were handed over to the `restore_all` function.
RestoreTwins { path: PathBuf, items: Vec<TrashItem> },
}

/// Removes a single file or directory.
///
/// # Example
///
/// ```
/// extern crate trash;
/// use std::fs::File;
/// use trash::remove;
/// File::create("remove_me").unwrap();
/// trash::remove("remove_me").unwrap();
/// assert!(File::open("remove_me").is_err());
/// ```
pub fn remove<T: AsRef<Path>>(path: T) -> Result<(), Error> {
platform::remove(path)
}

/// Removes all files/directories specified by the collection of paths provided as an argument.
///
/// # Example
///
/// ```
/// extern crate trash;
/// use std::fs::File;
/// use trash::remove_all;
/// File::create("remove_me_1").unwrap();
/// File::create("remove_me_2").unwrap();
/// remove_all(&["remove_me_1", "remove_me_2"]).unwrap();
/// assert!(File::open("remove_me_1").is_err());
/// assert!(File::open("remove_me_2").is_err());
/// ```
pub fn remove_all<I, T>(paths: I) -> Result<(), Error>
where
I: IntoIterator<Item = T>,
T: AsRef<Path>,
{
platform::remove_all(paths)
}

/// This struct holds information about a single item within the trash.
///
/// Some functions associated with this struct are defined in the `TrahsItemPlatformDep` trait.
Expand Down Expand Up @@ -205,6 +246,7 @@ pub struct TrashItem {
/// The date and time in UNIX Epoch time when the item was put into the trash.
pub time_deleted: i64,
}

/// Platform independent functions of `TrashItem`.
///
/// See `TrahsItemPlatformDep` for platform dependent functions.
Expand All @@ -226,54 +268,14 @@ impl Hash for TrashItem {
}
}

/// Removes a single file or directory.
///
/// # Example
///
/// ```
/// extern crate trash;
/// use std::fs::File;
/// use trash::remove;
/// File::create("remove_me").unwrap();
/// trash::remove("remove_me").unwrap();
/// assert!(File::open("remove_me").is_err());
/// ```
pub fn remove<T: AsRef<Path>>(path: T) -> Result<(), Error> {
platform::remove(path)
}

/// Removes all files/directories specified by the collection of paths provided as an argument.
///
/// # Example
///
/// ```
/// extern crate trash;
/// use std::fs::File;
/// use trash::remove_all;
/// File::create("remove_me_1").unwrap();
/// File::create("remove_me_2").unwrap();
/// remove_all(&["remove_me_1", "remove_me_2"]).unwrap();
/// assert!(File::open("remove_me_1").is_err());
/// assert!(File::open("remove_me_2").is_err());
/// ```
pub fn remove_all<I, T>(paths: I) -> Result<(), Error>
where
I: IntoIterator<Item = T>,
T: AsRef<Path>,
{
platform::remove_all(paths)
}

#[cfg(any(target_os = "linux", target_os = "windows"))]
pub mod linux_windows {
//!
//! This module contains functions that are only available on Windows and Linux.
//! See the [crate description] for more.
//!
//! [crate description]: ../index.html
//!
#[cfg(all(unix, not(target_os = "macos")))]
pub mod extra {
use std::{
collections::HashSet,
hash::{Hash, Hasher},
};

use super::*;
use super::{platform, Error, ErrorKind, TrashItem};

/// Returns all [`TrashItem`]s that are currently in the trash.
///
Expand Down
2 changes: 1 addition & 1 deletion src/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ fn get_mount_points() -> Result<Vec<MountPoint>, Error> {
if file == std::ptr::null_mut() {
panic!("Neither '/proc/mounts' nor '/etc/mtab' could be opened.");
}
defer! {{ unsafe { libc::fclose(file); } }}
defer! { unsafe { libc::fclose(file); } }
let mut result = Vec::new();
loop {
let mntent = unsafe { libc::getmntent(file) };
Expand Down
37 changes: 18 additions & 19 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ fn create_multiple_remove_all() {
}

#[cfg(any(target_os = "linux", target_os = "windows"))]
mod linux_windows {
mod extra {
use super::*;

#[test]
Expand All @@ -81,7 +81,7 @@ mod linux_windows {
}
trash::remove_all(&names).unwrap();
}
let items = trash::linux_windows::list().unwrap();
let items = trash::extra::list().unwrap();
let items: HashMap<_, Vec<_>> = items
.into_iter()
.filter(|x| x.name.starts_with(&file_name_prefix))
Expand All @@ -105,18 +105,17 @@ mod linux_windows {

// 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::linux_windows::purge_all(items.into_iter().map(|(_name, item)| item).flatten());
let _ = trash::extra::purge_all(items.into_iter().map(|(_name, item)| item).flatten());
}

#[test]
fn purge_empty() {
trash::linux_windows::purge_all(vec![]).unwrap();
trash::extra::purge_all(vec![]).unwrap();
}

#[test]
fn restore_empty() {
trash::linux_windows::restore_all(vec![]).unwrap();
trash::extra::restore_all(vec![]).unwrap();
}

#[test]
Expand All @@ -134,14 +133,14 @@ mod linux_windows {
}

// Collect it because we need the exact number of items gathered.
let targets: Vec<_> = trash::linux_windows::list()
let targets: Vec<_> = trash::extra::list()
.unwrap()
.into_iter()
.filter(|x| x.name.starts_with(&file_name_prefix))
.collect();
assert_eq!(targets.len(), batches * files_per_batch);
trash::linux_windows::purge_all(targets).unwrap();
let remaining = trash::linux_windows::list()
trash::extra::purge_all(targets).unwrap();
let remaining = trash::extra::list()
.unwrap()
.into_iter()
.filter(|x| x.name.starts_with(&file_name_prefix))
Expand All @@ -161,14 +160,14 @@ mod linux_windows {
trash::remove_all(&names).unwrap();

// Collect it because we need the exact number of items gathered.
let targets: Vec<_> = trash::linux_windows::list()
let targets: Vec<_> = trash::extra::list()
.unwrap()
.into_iter()
.filter(|x| x.name.starts_with(&file_name_prefix))
.collect();
assert_eq!(targets.len(), file_count);
trash::linux_windows::restore_all(targets).unwrap();
let remaining = trash::linux_windows::list()
trash::extra::restore_all(targets).unwrap();
let remaining = trash::extra::list()
.unwrap()
.into_iter()
.filter(|x| x.name.starts_with(&file_name_prefix))
Expand Down Expand Up @@ -200,15 +199,15 @@ mod linux_windows {
for path in names.iter().skip(file_count - collision_remaining) {
File::create(path).unwrap();
}
let mut targets: Vec<_> = trash::linux_windows::list()
let mut targets: Vec<_> = trash::extra::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::linux_windows::restore_all(targets) {
match trash::extra::restore_all(targets) {
Err(e) => match e.kind() {
trash::ErrorKind::RestoreCollision { remaining_items, .. } => {
let contains = |v: &Vec<trash::TrashItem>, name: &String| {
Expand All @@ -231,13 +230,13 @@ mod linux_windows {
"restore_all was expected to return `trash::ErrorKind::RestoreCollision` but did not."
),
}
let remaining = trash::linux_windows::list()
let remaining = trash::extra::list()
.unwrap()
.into_iter()
.filter(|x| x.name.starts_with(&file_name_prefix))
.collect::<Vec<_>>();
assert_eq!(remaining.len(), remaining_count);
trash::linux_windows::purge_all(remaining).unwrap();
trash::extra::purge_all(remaining).unwrap();
for path in names.iter() {
// This will obviously fail on the items that both didn't collide and weren't restored.
let _ = std::fs::remove_file(path);
Expand All @@ -259,20 +258,20 @@ mod linux_windows {
File::create(twin_name).unwrap();
trash::remove(&twin_name).unwrap();

let mut targets: Vec<_> = trash::linux_windows::list()
let mut targets: Vec<_> = trash::extra::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 + 1); // plus one for one of the twins
match trash::linux_windows::restore_all(targets) {
match trash::extra::restore_all(targets) {
Err(e) => match e.kind() {
trash::ErrorKind::RestoreTwins { path, .. } => {
assert_eq!(path.file_name().unwrap().to_str().unwrap(), twin_name);
match e.into_kind() {
trash::ErrorKind::RestoreTwins { items, .. } => {
trash::linux_windows::purge_all(items).unwrap();
trash::extra::purge_all(items).unwrap();
}
_ => unreachable!(),
}
Expand Down

0 comments on commit 314e808

Please sign in to comment.