code optimizations

This commit is contained in:
sreedev
2023-01-13 20:54:09 -05:00
parent 0031891b8b
commit 81c96ce3b8
7 changed files with 62 additions and 56 deletions

View File

@@ -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(())

View File

@@ -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 {

View File

@@ -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<File>) -> Result<()> {
files.into_iter().for_each(|file| {
match std::fs::remove_file(file.path.clone()) {

View File

@@ -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;

View File

@@ -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<String> {
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<bool> {
match user_input.trim() {
"Y" | "y" => Ok(true),
_ => Ok(false)
_ => Ok(false),
}
}
@@ -107,20 +104,27 @@ fn process_group_action(duplicates: &Vec<File>, 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<File>, 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<File>, opts: &Params) {

View File

@@ -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 {

View File

@@ -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<Vec<File>> {
let scan_results = scan(app_opts, connection)?;
@@ -46,7 +43,12 @@ fn scan(app_opts: &Params, connection: &sqlite::Connection) -> Result<Vec<String
let indexed_paths = database::indexed_paths(connection)?;
let files: Vec<String> = 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<Vec<String
fn index_files(files: Vec<String>, connection: &sqlite::Connection) -> Result<()> {
let hashed: Vec<File> = 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();