From 64ab813ae6b80a7ef10b6f48c306972caf8ddfde Mon Sep 17 00:00:00 2001 From: 44r0n7 <44r0n7+gitea@pm.me> Date: Wed, 31 Dec 2025 23:29:21 -0500 Subject: [PATCH] ux: show scan/fix progress --- vid-repair/src/main.rs | 71 +++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/vid-repair/src/main.rs b/vid-repair/src/main.rs index bc7b702..c0ace87 100644 --- a/vid-repair/src/main.rs +++ b/vid-repair/src/main.rs @@ -296,6 +296,10 @@ fn handle_scan(args: ScanArgs, common: &CommonArgs) -> Result { return Ok(0); } + if !config.report.json { + eprintln!("Scanning {} file(s)...", files.len()); + } + let batch = run_scans(files, &config, &ruleset)?; let scans = batch.scans; let has_issues = scans.iter().any(|scan| !scan.issues.is_empty()); @@ -372,6 +376,14 @@ fn handle_fix(args: FixArgs, common: &CommonArgs) -> Result { return Ok(0); } + if !config.report.json { + if args.dry_run { + eprintln!("Planning fixes for {} file(s)...", files.len()); + } else { + eprintln!("Fixing {} file(s)...", files.len()); + } + } + let (scans, fixes, errors) = run_fixes(files, &config, &ruleset, args.dry_run)?; let fix_failed = fixes.iter().any(|fix| fix.applied && !fix.success); let has_issues = scans.iter().any(|scan| !scan.issues.is_empty()); @@ -417,18 +429,27 @@ fn run_scans(files: Vec, config: &Config, ruleset: &RuleSet) -> Result< }; let errors = AtomicUsize::new(0); + let started = AtomicUsize::new(0); + let total = files.len(); + let show_progress = !config.report.json; let scans = if let Some(jobs) = jobs { let pool = ThreadPoolBuilder::new().num_threads(jobs).build()?; pool.install(|| { files .par_iter() - .filter_map(|path| match scan_file(path, config, ruleset) { - Ok(scan) => Some(scan), - Err(err) => { - eprintln!("[ERROR] {}: {}", path.display(), err); - errors.fetch_add(1, Ordering::SeqCst); - None + .filter_map(|path| { + let idx = started.fetch_add(1, Ordering::SeqCst) + 1; + if show_progress { + eprintln!("[SCAN {}/{}] {}", idx, total, path.display()); + } + match scan_file(path, config, ruleset) { + Ok(scan) => Some(scan), + Err(err) => { + eprintln!("[ERROR] {}: {}", path.display(), err); + errors.fetch_add(1, Ordering::SeqCst); + None + } } }) .collect::>() @@ -436,12 +457,18 @@ fn run_scans(files: Vec, config: &Config, ruleset: &RuleSet) -> Result< } else { files .iter() - .filter_map(|path| match scan_file(path, config, ruleset) { - Ok(scan) => Some(scan), - Err(err) => { - eprintln!("[ERROR] {}: {}", path.display(), err); - errors.fetch_add(1, Ordering::SeqCst); - None + .filter_map(|path| { + let idx = started.fetch_add(1, Ordering::SeqCst) + 1; + if show_progress { + eprintln!("[SCAN {}/{}] {}", idx, total, path.display()); + } + match scan_file(path, config, ruleset) { + Ok(scan) => Some(scan), + Err(err) => { + eprintln!("[ERROR] {}: {}", path.display(), err); + errors.fetch_add(1, Ordering::SeqCst); + None + } } }) .collect::>() @@ -482,8 +509,15 @@ fn process_fix_batch( let mut scans = Vec::new(); let mut fixes = Vec::new(); let mut errors = 0usize; + let total = files.len(); + let show_progress = !config.report.json; + let mut idx = 0usize; for path in files { + idx += 1; + if show_progress { + eprintln!("[FIX {}/{}] {}", idx, total, path.display()); + } let scan = match scan_file(&path, config, ruleset) { Ok(scan) => scan, Err(err) => { @@ -522,9 +556,16 @@ fn process_fix_batch_parallel( dry_run: bool, ) -> Result<(Vec, Vec, usize)> { let errors = AtomicUsize::new(0); + let started = AtomicUsize::new(0); + let total = files.len(); + let show_progress = !config.report.json; let results = files .par_iter() .filter_map(|path| { + let idx = started.fetch_add(1, Ordering::SeqCst) + 1; + if show_progress { + eprintln!("[FIX {}/{}] {}", idx, total, path.display()); + } let scan = match scan_file(path, config, ruleset) { Ok(scan) => scan, Err(err) => { @@ -560,6 +601,9 @@ fn process_fix_batch_parallel( fn watch_scan(paths: Vec, config: &Config, ruleset: &RuleSet) -> Result<()> { println!("Watch mode enabled. Waiting for files to settle..."); watch::watch_paths(&paths, config, |path| { + if !config.report.json { + eprintln!("[SCAN] {}", path.display()); + } match scan_file(&path, config, ruleset) { Ok(scan) => { println!("{}", render_scan_line(&scan)); @@ -574,6 +618,9 @@ fn watch_scan(paths: Vec, config: &Config, ruleset: &RuleSet) -> Result fn watch_fix(paths: Vec, config: &Config, ruleset: &RuleSet, dry_run: bool) -> Result<()> { println!("Watch mode enabled. Waiting for files to settle..."); watch::watch_paths(&paths, config, |path| { + if !config.report.json { + eprintln!("[FIX] {}", path.display()); + } match scan_file(&path, config, ruleset) { Ok(scan) => { let plan = fix::planner::plan_fix(&scan.issues, config.repair.policy);