use crate::config::{OutputFormat, ScanFilter, ScanOptions};
use crate::output;
use crate::scan::{self, Catalog, FileEntry, ScanStats};
use crate::{cli, exit_error};
use std::fs;
use std::path::Path;
pub fn run_with_dialogs(options: &ScanOptions, filter: &ScanFilter) {
let folder = match rfd::FileDialog::new()
.set_title("Select Folder to Scan")
.pick_folder()
{
Some(path) => path,
None => {
eprintln!("No folder selected.");
std::process::exit(0);
}
};
let default_name = cli::default_filename(&folder, options.format.extension());
let output_path = match rfd::FileDialog::new()
.set_title("Select Output Location")
.set_file_name(&default_name)
.save_file()
{
Some(path) => path,
None => {
eprintln!("No output location selected.");
std::process::exit(0);
}
};
run(&folder, &output_path, options, filter);
}
pub fn run(folder: &Path, output_path: &Path, options: &ScanOptions, filter: &ScanFilter) {
if !folder.exists() {
eprintln!("Error: Folder '{}' does not exist", folder.display());
if folder.is_relative()
&& let Ok(cwd) = std::env::current_dir()
{
eprintln!("Current directory: {}", cwd.display());
eprintln!("Tried to resolve: {}", cwd.join(folder).display());
}
std::process::exit(1);
}
if !folder.is_dir() {
exit_error(&format!("'{}' is not a directory", folder.display()));
}
ensure_parent_dir(output_path);
let stats = match options.format {
OutputFormat::Csv => output::csv::write_streaming(folder, output_path, options, filter)
.unwrap_or_else(|e| exit_error(&format!("writing output file: {e}"))),
OutputFormat::Text | OutputFormat::Json => {
let mut catalog: Catalog = Catalog::new();
let stats = scan::walk(folder, options, filter, |ext, path, size| {
catalog.entry(ext).or_default().push(FileEntry { path, size });
});
write_grouped(&catalog, &stats, folder, output_path, options)
.unwrap_or_else(|e| exit_error(&format!("writing output file: {e}")));
stats
}
};
print_summary(&stats, options);
println!("Saved to: {}", output_path.display());
}
fn write_grouped(
catalog: &Catalog,
stats: &ScanStats,
folder: &Path,
output_path: &Path,
options: &ScanOptions,
) -> std::io::Result<()> {
match options.format {
OutputFormat::Json => output::json::write(catalog, stats, folder, output_path, options),
_ => output::text::write(catalog, output_path, options),
}
}
fn ensure_parent_dir(output_path: &Path) {
if let Some(parent) = output_path.parent()
&& !parent.as_os_str().is_empty()
&& let Err(e) = fs::create_dir_all(parent)
{
exit_error(&format!("creating output directory: {e}"));
}
}
fn print_summary(stats: &ScanStats, options: &ScanOptions) {
if options.sizes {
println!(
"Scanned {} files ({}) in {} directories ({} skipped, {} symlinks).",
stats.files,
output::human_size(stats.total_size),
stats.dirs,
stats.skipped,
stats.symlinks
);
} else {
println!(
"Scanned {} files in {} directories ({} skipped, {} symlinks).",
stats.files, stats.dirs, stats.skipped, stats.symlinks
);
}
}