diff --git a/src/app.rs b/src/app.rs index 17fc63f..3356b25 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,12 +1,8 @@ -#![allow(unused)] - -use std::{io, thread, time::Duration}; -use anyhow::{anyhow, Result}; -use crossterm::{event, execute, terminal}; use crate::database; use crate::output; use crate::params::Params; use crate::scanner; +use anyhow::Result; pub struct App; @@ -14,10 +10,9 @@ impl App { pub fn init(app_args: &Params) -> Result<()> { let connection = database::get_connection(app_args)?; let duplicates = scanner::duplicates(app_args, &connection)?; - match app_args.interactive { true => output::interactive(duplicates, app_args), - false => output::print(duplicates, app_args) + false => output::print(duplicates, app_args), } Ok(()) diff --git a/src/database.rs b/src/database.rs index 371d41f..3f8595c 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,14 +1,7 @@ use std::env::temp_dir; - use anyhow::Result; - use crate::params::Params; - -#[derive(Debug, Clone)] -pub struct File { - pub path: String, - pub hash: String, -} +use crate::file_manager::File; fn db_connection_url(args: &Params) -> String { match args.nocache { diff --git a/src/file_manager.rs b/src/file_manager.rs index 4f57d81..9f97318 100644 --- a/src/file_manager.rs +++ b/src/file_manager.rs @@ -1,7 +1,12 @@ -use crate::database::File; use anyhow::Result; use colored::Colorize; +#[derive(Debug, Clone)] +pub struct File { + pub path: String, + pub hash: String, +} + pub fn delete_files(files: Vec) -> Result<()> { files.into_iter().for_each(|file| { match std::fs::remove_file(file.path.clone()) { diff --git a/src/main.rs b/src/main.rs index b07a679..25b703c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,9 @@ mod app; mod database; +mod file_manager; mod output; mod params; mod scanner; -mod file_manager; use anyhow::Result; use app::App; diff --git a/src/output.rs b/src/output.rs index 9987374..b52eca5 100644 --- a/src/output.rs +++ b/src/output.rs @@ -1,21 +1,18 @@ -use std::{collections::HashMap, fs, io}; use std::io::Write; - +use std::{collections::HashMap, fs, io}; use anyhow::Result; use chrono::offset::Utc; use chrono::DateTime; use colored::Colorize; use humansize::{format_size, DECIMAL}; use itertools::Itertools; - -use crate::file_manager; -use crate::database::File; +use crate::file_manager::{self, File}; use crate::params::Params; use prettytable::{format, row, Table}; use unicode_segmentation::UnicodeSegmentation; fn format_path(path: &str, opts: &Params) -> Result { - let display_path = path.replace(&opts.get_directory()?, ""); + let display_path = path.replace(&opts.get_directory()?, ""); let display_range = if display_path.chars().count() > 32 { display_path .graphemes(true) @@ -81,7 +78,7 @@ fn scan_group_confirmation() -> Result { match user_input.trim() { "Y" | "y" => Ok(true), - _ => Ok(false) + _ => Ok(false), } } @@ -107,20 +104,27 @@ fn process_group_action(duplicates: &Vec, dup_index: usize, dup_size: usiz print!("{esc}[2J{esc}[1;1H", esc = 27 as char); - if parsed_file_indices.is_empty() { return } + if parsed_file_indices.is_empty() { + return; + } let files_to_delete = parsed_file_indices .into_iter() .map(|index| duplicates[index].clone()); println!("\n{}", "The following files will be deleted:".red()); - files_to_delete.clone().enumerate().for_each(|(index, file)| { - println!("{}: {}", index.to_string().blue(), file.path); - }); - + files_to_delete + .clone() + .enumerate() + .for_each(|(index, file)| { + println!("{}: {}", index.to_string().blue(), file.path); + }); + match scan_group_confirmation().unwrap() { - true => { file_manager::delete_files(files_to_delete.collect_vec()); }, - false => println!("{}", "\nCancelled Delete Operation.".red()) + true => { + file_manager::delete_files(files_to_delete.collect_vec()); + } + false => println!("{}", "\nCancelled Delete Operation.".red()), } } @@ -128,21 +132,24 @@ pub fn interactive(duplicates: Vec, opts: &Params) { print_meta_info(&duplicates, opts); let grouped_duplicates = group_duplicates(duplicates); - grouped_duplicates.iter().enumerate().for_each(|(gindex, (hash, group))| { - let mut itable = Table::new(); - itable.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR); - itable.set_titles(row!["index", "filename", "size", "updated_at"]); - group.iter().enumerate().for_each(|(index, file)| { - itable.add_row(row![ - index, - format_path(&file.path, opts).unwrap_or_default().blue(), - file_size(&file.path).unwrap_or_default().red(), - modified_time(&file.path).unwrap_or_default().yellow() - ]); - }); + grouped_duplicates + .iter() + .enumerate() + .for_each(|(gindex, (hash, group))| { + let mut itable = Table::new(); + itable.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR); + itable.set_titles(row!["index", "filename", "size", "updated_at"]); + group.iter().enumerate().for_each(|(index, file)| { + itable.add_row(row![ + index, + format_path(&file.path, opts).unwrap_or_default().blue(), + file_size(&file.path).unwrap_or_default().red(), + modified_time(&file.path).unwrap_or_default().yellow() + ]); + }); - process_group_action(group, gindex, grouped_duplicates.len(), itable); - }); + process_group_action(group, gindex, grouped_duplicates.len(), itable); + }); } pub fn print(duplicates: Vec, opts: &Params) { diff --git a/src/params.rs b/src/params.rs index 11741d9..5694eec 100644 --- a/src/params.rs +++ b/src/params.rs @@ -1,5 +1,4 @@ use std::{fs, path::PathBuf}; - use anyhow::{anyhow, Result}; use clap::Parser; @@ -17,7 +16,7 @@ pub struct Params { pub nocache: bool, /// Delete files interactively #[arg(long, short)] - pub interactive: bool + pub interactive: bool, } impl Params { diff --git a/src/scanner.rs b/src/scanner.rs index 21bb3ab..ba0fc6c 100644 --- a/src/scanner.rs +++ b/src/scanner.rs @@ -1,15 +1,12 @@ -use std::{fs, path::PathBuf}; -use indicatif::{HumanDuration, MultiProgress, ProgressBar, ProgressStyle, ParallelProgressIterator}; use anyhow::Result; use fxhash::hash32 as hasher; use glob::glob; +use indicatif::{ParallelProgressIterator, ProgressStyle}; use itertools::Itertools; use rayon::prelude::*; +use std::{fs, path::PathBuf}; -use crate::{ - database::{self, File}, - params::Params, -}; +use crate::{database, file_manager::File, params::Params}; pub fn duplicates(app_opts: &Params, connection: &sqlite::Connection) -> Result> { let scan_results = scan(app_opts, connection)?; @@ -46,7 +43,12 @@ fn scan(app_opts: &Params, connection: &sqlite::Connection) -> Result = glob_patterns .par_iter() - .progress_with_style(ProgressStyle::with_template("{spinner:.green} [scanning files] [{wide_bar:.cyan/blue}] {pos}/{len} files").unwrap()) + .progress_with_style( + ProgressStyle::with_template( + "{spinner:.green} [scanning files] [{wide_bar:.cyan/blue}] {pos}/{len} files", + ) + .unwrap(), + ) .filter_map(|glob_pattern| glob(glob_pattern.as_os_str().to_str()?).ok()) .flat_map(|file_vec| { file_vec @@ -67,10 +69,15 @@ fn scan(app_opts: &Params, connection: &sqlite::Connection) -> Result, connection: &sqlite::Connection) -> Result<()> { let hashed: Vec = files .into_par_iter() - .progress_with_style(ProgressStyle::with_template("{spinner:.green} [indexing files] [{wide_bar:.cyan/blue}] {pos}/{len} files").unwrap()) + .progress_with_style( + ProgressStyle::with_template( + "{spinner:.green} [indexing files] [{wide_bar:.cyan/blue}] {pos}/{len} files", + ) + .unwrap(), + ) .filter_map(|file| { let hash = hash_file(&file).ok()?; - Some(database::File { path: file, hash }) + Some(File { path: file, hash }) }) .collect();