diff --git a/Cargo.lock b/Cargo.lock index fe01363..a64af0a 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -683,6 +683,15 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -832,7 +841,7 @@ dependencies = [ [[package]] name = "trasher" -version = "3.3.5" +version = "3.3.6" dependencies = [ "anyhow", "base64", @@ -849,6 +858,7 @@ dependencies = [ "ratatui", "regex", "tui-input", + "walkdir", ] [[package]] @@ -891,6 +901,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -967,6 +987,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index a688d92..6a9a2e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "trasher" -version = "3.3.5" +version = "3.3.6" authors = ["Clément Nerma "] edition = "2021" license = "Apache-2.0" @@ -30,3 +30,4 @@ mountpoints = "0.2.1" indicatif = "0.17.8" fs_extra = "1.3.0" comfy-table = "7.1.0" +walkdir = "2.5.0" diff --git a/src/actions.rs b/src/actions.rs index fde9e9e..0bf4dd3 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -1,8 +1,9 @@ use std::{fs, io::stdin, path::PathBuf}; use anyhow::{Context, Result}; +use indicatif::{ProgressBar, ProgressStyle}; -use crate::{error, fuzzy::FuzzyFinderItem, info, success, warn}; +use crate::{fuzzy::FuzzyFinderItem, info, success, warn}; use super::{args::*, bail, debug, fsutils::*, items::*}; @@ -330,23 +331,42 @@ pub fn empty(config: &Config) -> Result<()> { info!("Emptying the trash..."); - let mut failed = false; - for trash_dir in trash_dirs { info!("Emptying trash directory: {}", trash_dir.display()); - if let Err(err) = fs::remove_dir_all(&trash_dir) { - error!( - "Failed to empty the trash at path: {}\n> {err}\n", - trash_dir.display() - ); + warn!("> Listing files and directories to delete..."); + + let items = list_deletable_fs_items(&trash_dir)?; + + warn!("> Deleting all {} items...", items.len()); + + let pbr = ProgressBar::new(items.len().try_into().unwrap()); + + pbr.set_style(ProgressStyle::default_bar() + .template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {bytes}/{total_bytes} ({eta})") + .expect("Invalid progress bar template") + .progress_chars("#>-")); + + for (i, item) in items.iter().enumerate() { + let metadata = item + .symlink_metadata() + .with_context(|| format!("Failed to get metadata for item: {}", item.display()))? + .file_type(); - failed = true; + if metadata.is_dir() { + fs::remove_dir(item) + .with_context(|| format!("Failed to remove directory: {}", item.display()))?; + } else { + fs::remove_file(item) + .with_context(|| format!("Failed to remove file: {}", item.display()))?; + } + + if i % 25 == 0 || i + 1 == items.len() { + pbr.set_position((i + 1).try_into().unwrap()); + } } - } - if failed { - bail!("Failed to empty trash directories"); + pbr.finish(); } success!("Trash was successfully emptied."); diff --git a/src/fsutils.rs b/src/fsutils.rs index 3ae4985..c2d6927 100755 --- a/src/fsutils.rs +++ b/src/fsutils.rs @@ -13,6 +13,7 @@ use comfy_table::{presets::UTF8_FULL_CONDENSED, ContentArrangement, Table}; use fs_extra::dir::TransitProcessResult; use indicatif::{ProgressBar, ProgressStyle}; use mountpoints::mountpaths; +use walkdir::WalkDir; use crate::{debug, error, Config}; @@ -465,3 +466,12 @@ pub fn are_on_same_fs(a: &Path, b: &Path) -> Result { Ok(a_fs_id == b_fs_id) } + +pub fn list_deletable_fs_items(path: &Path) -> Result> { + WalkDir::new(path) + .contents_first(true) + .into_iter() + .map(|entry| entry.map(|entry| entry.into_path())) + .collect::, _>>() + .context("Failed to read directory entry") +}