diff --git a/src/catalog.rs b/src/catalog.rs index c0717c9..aa8fc74 100644 --- a/src/catalog.rs +++ b/src/catalog.rs @@ -6,7 +6,7 @@ use crate::suggestion::{ Action, InstallSpec, PurgeSpec, Scope, Suggestion, SweepSpec, Tag, TomlChange, TomlOp, TomlValue, }; -use crate::system::{SystemReport, have, human_bytes}; +use crate::system::{SystemReport, dir_size_bytes, have, human_bytes}; use crate::toml_ops; use std::path::{Path, PathBuf}; @@ -176,6 +176,29 @@ pub fn build(r: &SystemReport) -> Vec { // the install instead, and a re-run of frd then surfaces the sweep (the same // install-then-rerun flow sccache uses above). if have("cargo-sweep") { + let global_target = PathBuf::from(shared_target_dir()); + if global_target.exists() { + if let Some(bytes) = dir_size_bytes(&global_target) { + if bytes > 0 { + out.push(sweep_sug( + "Sweep stale build artifacts (recommended)", + Tag::Disk, + format!( + "Found {} in {}. Removes artifacts untouched for more than 7 days \ + while keeping warm ones.", + human_bytes(bytes), + shared_target_dir() + ), + SweepSpec { + candidates: vec![global_target], + time_days: 7, + sweep_all: true, + }, + )); + } + } + } + out.push(sweep_sug( "Sweep stale build artifacts", Tag::Disk, @@ -185,6 +208,7 @@ pub fn build(r: &SystemReport) -> Vec { SweepSpec { candidates: sweep_candidates(&p.root), time_days: 7, + sweep_all: false, }, )); } else { diff --git a/src/suggestion.rs b/src/suggestion.rs index 439dcf6..578fed9 100644 --- a/src/suggestion.rs +++ b/src/suggestion.rs @@ -95,13 +95,18 @@ impl RunSpec { pub struct SweepSpec { pub candidates: Vec, pub time_days: u32, + pub sweep_all: bool, } impl SweepSpec { /// The base command, without the directory (resolved interactively at accept /// time). Used by the doctor's read-only maintenance listing. pub fn display(&self) -> String { - format!("cargo sweep --time {}", self.time_days) + if self.sweep_all { + "cargo sweep --all --recursive".to_string() + } else { + format!("cargo sweep --time {}", self.time_days) + } } } diff --git a/src/wizard.rs b/src/wizard.rs index f455e5b..2d8fdd1 100644 --- a/src/wizard.rs +++ b/src/wizard.rs @@ -144,12 +144,12 @@ fn show_card( } else { format!("a dir you pick ยท {} options up to ~", s.candidates.len()) }; - body.push_str(&format!( - "\n\n{} cargo sweep --time {} {}", - style("run").bold(), - s.time_days, - style(scope).dim(), - )); + let cmd = if s.sweep_all { + format!("cargo sweep --all --recursive {}", scope) + } else { + format!("cargo sweep --time {} {}", s.time_days, scope) + }; + body.push_str(&format!("\n\n{} {}", style("run").bold(), style(cmd).dim(),)); } Action::Purge(s) => { let scope = if s.candidates.len() == 1 { @@ -237,7 +237,7 @@ fn filename(path: &Path) -> String { fn run_sweep(spec: &SweepSpec, tag: Tag, runner: &Runner, dry_run: bool, yes: bool) -> Result<()> { let dir = pick_dir(&spec.candidates, yes, "Which directory to sweep?")?; let recursive = dir != spec.candidates[0]; - let run = sweep_runspec(&dir, spec.time_days, recursive); + let run = sweep_runspec(&dir, spec.time_days, recursive, spec.sweep_all); if dry_run { return runner.run(&run, tag, true); @@ -372,9 +372,16 @@ fn pick_dir(candidates: &[PathBuf], yes: bool, prompt: &str) -> Result .map_err(|e| anyhow!("interactive prompt needs a TTY; use --yes: {e}")) } -fn sweep_runspec(dir: &Path, time_days: u32, recursive: bool) -> RunSpec { - let mut args = vec!["sweep".into(), "--time".into(), time_days.to_string()]; - if recursive { +fn sweep_runspec(dir: &Path, time_days: u32, recursive: bool, sweep_all: bool) -> RunSpec { + let mut args = vec!["sweep".into()]; + if sweep_all { + args.push("--all".into()); + args.push("--recursive".into()); + } else { + args.push("--time".into()); + args.push(time_days.to_string()); + } + if recursive && !sweep_all { args.push("--recursive".into()); } RunSpec {