ux: show scan/fix progress

This commit is contained in:
2025-12-31 23:29:21 -05:00
parent 9bd14a790a
commit 64ab813ae6

View File

@@ -296,6 +296,10 @@ fn handle_scan(args: ScanArgs, common: &CommonArgs) -> Result<i32> {
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<i32> {
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<PathBuf>, 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::<Vec<_>>()
@@ -436,12 +457,18 @@ fn run_scans(files: Vec<PathBuf>, 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::<Vec<_>>()
@@ -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<ScanOutcome>, Vec<FixOutcome>, 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<PathBuf>, 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<PathBuf>, config: &Config, ruleset: &RuleSet) -> Result
fn watch_fix(paths: Vec<PathBuf>, 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);