mirror of
https://github.com/sreedevk/deduplicator.git
synced 2026-09-07 10:34:22 +00:00
output formatting and printing performance improvements
This commit is contained in:
@@ -2,20 +2,17 @@ use crate::{fileinfo::FileInfo, params::Params};
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use indicatif::{ParallelProgressIterator, ProgressBar, ProgressFinish, ProgressStyle};
|
|
||||||
use pathdiff::diff_paths;
|
use pathdiff::diff_paths;
|
||||||
use prettytable::{format, row, Row, Table};
|
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use std::{borrow::Cow, path::PathBuf, sync::Arc, time::Duration};
|
use std::{path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
|
const YELLOW: &str = "\x1b[33m";
|
||||||
|
const RESET: &str = "\x1b[0m";
|
||||||
|
|
||||||
pub struct Formatter;
|
pub struct Formatter;
|
||||||
impl Formatter {
|
impl Formatter {
|
||||||
pub fn human_path(
|
pub fn human_path(file: &FileInfo, aargs: &Params, min_path_length: usize) -> Result<String> {
|
||||||
file: &FileInfo,
|
let base_directory: PathBuf = aargs.get_directory()?;
|
||||||
app_args: &Params,
|
|
||||||
min_path_length: usize,
|
|
||||||
) -> Result<String> {
|
|
||||||
let base_directory: PathBuf = app_args.get_directory()?;
|
|
||||||
let relative_path = diff_paths(&file.path, base_directory).unwrap_or_default();
|
let relative_path = diff_paths(&file.path, base_directory).unwrap_or_default();
|
||||||
|
|
||||||
let formatted_path = format!(
|
let formatted_path = format!(
|
||||||
@@ -36,70 +33,33 @@ impl Formatter {
|
|||||||
Ok(modified_time.format("%Y-%m-%d %H:%M:%S").to_string())
|
Ok(modified_time.format("%Y-%m-%d %H:%M:%S").to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash_hex(hash: &u128) -> Box<str> {
|
pub fn print(raw: Arc<DashMap<u128, Vec<FileInfo>>>, max_path_len: u64, aargs: &Params) {
|
||||||
format!("{:32x}", hash).into_boxed_str()
|
print!("\n\n\n"); // spacing
|
||||||
}
|
|
||||||
|
|
||||||
pub fn gen_sub_tbl(items: Vec<FileInfo>, app_args: &Params, max_path_len: u64) -> Table {
|
|
||||||
let mut inner_table = Table::new();
|
|
||||||
inner_table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
|
|
||||||
items.iter().for_each(|file| {
|
|
||||||
inner_table.add_row(row![
|
|
||||||
Self::human_path(file, app_args, max_path_len as usize).unwrap_or_default(),
|
|
||||||
Self::human_filesize(file).unwrap_or_default(),
|
|
||||||
Self::human_mtime(file).unwrap_or_default()
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
inner_table
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate_table(
|
|
||||||
raw: Arc<DashMap<u128, Vec<FileInfo>>>,
|
|
||||||
mpath_len: u64,
|
|
||||||
args: &Params,
|
|
||||||
) -> Result<Table> {
|
|
||||||
let progress_bar = match args.progress {
|
|
||||||
true => ProgressBar::new_spinner(),
|
|
||||||
false => ProgressBar::hidden(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let progress_style = ProgressStyle::with_template("[{elapsed_precise}] {pos:>7} {msg}")?;
|
|
||||||
progress_bar.set_style(progress_style);
|
|
||||||
progress_bar.enable_steady_tick(Duration::from_millis(50));
|
|
||||||
progress_bar.set_message("generating output");
|
|
||||||
|
|
||||||
let rows = raw
|
|
||||||
.par_iter_mut()
|
|
||||||
.progress_with(progress_bar)
|
|
||||||
.with_finish(ProgressFinish::WithMessage(Cow::from("output generated")))
|
|
||||||
.filter(|i| i.value().len() > 1)
|
|
||||||
.map(|i| {
|
|
||||||
row![
|
|
||||||
Self::hash_hex(i.key()),
|
|
||||||
Self::gen_sub_tbl(i.value().to_vec(), args, mpath_len)
|
|
||||||
]
|
|
||||||
})
|
|
||||||
.collect::<Vec<Row>>();
|
|
||||||
|
|
||||||
let mut output_table = Table::new();
|
|
||||||
output_table.set_titles(row!["hash", "duplicates"]);
|
|
||||||
output_table.extend(rows);
|
|
||||||
Ok(output_table)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn print(
|
|
||||||
raw: Arc<DashMap<u128, Vec<FileInfo>>>,
|
|
||||||
max_path_len: u64,
|
|
||||||
app_args: &Params,
|
|
||||||
) -> Result<()> {
|
|
||||||
if raw.is_empty() {
|
if raw.is_empty() {
|
||||||
println!("\n\nNo duplicates found matching your search criteria.\n");
|
println!("No duplicates found matching your search criteria.");
|
||||||
return Ok(());
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let output_table = Self::generate_table(raw, max_path_len, app_args)?;
|
raw.par_iter().for_each(|sref| {
|
||||||
output_table.printstd();
|
let mut ostring = format!("{}{:32x}{}\n", YELLOW, sref.key(), RESET);
|
||||||
|
let subfields = sref
|
||||||
|
.value()
|
||||||
|
.par_iter()
|
||||||
|
.map(|finfo| {
|
||||||
|
format!(
|
||||||
|
"├─ {}\t{}\t{}\n",
|
||||||
|
Self::human_path(finfo, aargs, max_path_len as usize)
|
||||||
|
.expect("path formatting failed."),
|
||||||
|
Self::human_filesize(finfo).expect("filesize formatting failed."),
|
||||||
|
Self::human_mtime(finfo).expect("modified time formatting failed.")
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<String>();
|
||||||
|
|
||||||
Ok(())
|
ostring.push_str(&subfields);
|
||||||
|
|
||||||
|
println!("{ostring}");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ fn main() -> Result<()> {
|
|||||||
server.hw_duplicate_set,
|
server.hw_duplicate_set,
|
||||||
server.max_file_path_len.load(Ordering::Acquire),
|
server.max_file_path_len.load(Ordering::Acquire),
|
||||||
&app_args,
|
&app_args,
|
||||||
)?;
|
);
|
||||||
}
|
}
|
||||||
true => {
|
true => {
|
||||||
Interactive::init(server.hw_duplicate_set, &app_args)?;
|
Interactive::init(server.hw_duplicate_set, &app_args)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user