|
@@ -1,6 +1,7 @@
|
|
|
-use std::{fs, path::PathBuf, process, env};
|
|
|
+use std::{env, fs, path::PathBuf, process, time::SystemTime};
|
|
|
+use anyhow::Result as anyResult;
|
|
|
|
|
|
-fn find_target_dir(path: PathBuf) -> Result<bool, std::io::Error> {
|
|
|
+fn find_target_dir(path: PathBuf) -> anyResult<bool> {
|
|
|
let mut found_target_dir: bool = false;
|
|
|
let mut found_cargo_toml: bool = false;
|
|
|
for entry in fs::read_dir(path)? {
|
|
@@ -15,7 +16,38 @@ fn find_target_dir(path: PathBuf) -> Result<bool, std::io::Error> {
|
|
|
Ok(found_target_dir && found_cargo_toml)
|
|
|
}
|
|
|
|
|
|
-fn execute_clean(path: PathBuf) -> Result<(), std::io::Error> {
|
|
|
+fn find_newest_file(path: PathBuf) -> anyResult<PathBuf> {
|
|
|
+ let mut pat: PathBuf = path.clone();
|
|
|
+ let mut pat_dif: SystemTime = SystemTime::now();
|
|
|
+ for entry in fs::read_dir(&path)? {
|
|
|
+ let entry = entry?;
|
|
|
+ let p = entry.path();
|
|
|
+ if !p.is_file() {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ let meta = entry.metadata()?;
|
|
|
+ let modif = meta.modified()?;
|
|
|
+ let access = meta.accessed()?;
|
|
|
+ if pat_dif.elapsed()?.as_secs() == 0 {
|
|
|
+ pat = path.join(p);
|
|
|
+ if modif.ge(&access) {
|
|
|
+ pat_dif = modif;
|
|
|
+ } else {
|
|
|
+ pat_dif = access;
|
|
|
+ }
|
|
|
+ } else if pat_dif.le(&modif) || pat_dif.le(&access) {
|
|
|
+ pat = path.join(p);
|
|
|
+ if modif.ge(&access) {
|
|
|
+ pat_dif = modif;
|
|
|
+ } else {
|
|
|
+ pat_dif = access;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Ok(pat)
|
|
|
+}
|
|
|
+
|
|
|
+fn execute_clean(path: PathBuf) -> anyResult<()> {
|
|
|
let _cmd = process::Command::new("cargo")
|
|
|
.current_dir(path)
|
|
|
.arg("clean")
|
|
@@ -23,7 +55,7 @@ fn execute_clean(path: PathBuf) -> Result<(), std::io::Error> {
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
-fn clean_in_dir(path: PathBuf) -> Result<u64, std::io::Error> {
|
|
|
+fn clean_in_dir(path: PathBuf, verbose: bool, forced: bool) -> anyResult<u64> {
|
|
|
let mut cleaned: u64 = 0;
|
|
|
for entry in fs::read_dir(path)? {
|
|
|
let entry = entry?;
|
|
@@ -31,12 +63,36 @@ fn clean_in_dir(path: PathBuf) -> Result<u64, std::io::Error> {
|
|
|
if p.is_dir() {
|
|
|
let needed = find_target_dir(p.clone())?;
|
|
|
if needed {
|
|
|
- println!(" => {}", p.display());
|
|
|
+ if !forced {
|
|
|
+ // If forced no need to check
|
|
|
+ let newest = find_newest_file(p.clone())?;
|
|
|
+ let meta = fs::metadata(newest)?;
|
|
|
+ let modif = meta.modified()?;
|
|
|
+ let access = meta.accessed()?;
|
|
|
+ let el: u64;
|
|
|
+ if modif.ge(&access) {
|
|
|
+ el = modif.elapsed()?.as_secs();
|
|
|
+ } else {
|
|
|
+ el = access.elapsed()?.as_secs();
|
|
|
+ }
|
|
|
+ let days = el / 86400;
|
|
|
+ if days < 30 {
|
|
|
+ if verbose {
|
|
|
+ println!(" => {} (dirty, {} days)", p.display(), days);
|
|
|
+ }
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if !verbose {
|
|
|
+ println!(" => {}", p.display());
|
|
|
+ } else {
|
|
|
+ println!(" => {} (dirty)", p.display());
|
|
|
+ }
|
|
|
execute_clean(p)?;
|
|
|
cleaned += 1;
|
|
|
} else {
|
|
|
// Maybe nested?
|
|
|
- let r = clean_in_dir(p)?;
|
|
|
+ let r = clean_in_dir(p, verbose, forced)?;
|
|
|
cleaned += r;
|
|
|
}
|
|
|
}
|
|
@@ -44,10 +100,23 @@ fn clean_in_dir(path: PathBuf) -> Result<u64, std::io::Error> {
|
|
|
Ok(cleaned)
|
|
|
}
|
|
|
|
|
|
-fn main() -> Result<(), std::io::Error> {
|
|
|
+fn main() -> anyResult<()> {
|
|
|
+ let mut verbose: bool = false;
|
|
|
+ let mut forced: bool = false;
|
|
|
+ for a in env::args() {
|
|
|
+ if a == "v" || a == "V" || a.to_lowercase() == "verbose" {
|
|
|
+ verbose = true;
|
|
|
+ println!("Verbose");
|
|
|
+ } else if a == "f" || a == "F" || a.to_lowercase().starts_with("force") {
|
|
|
+ forced = true;
|
|
|
+ if verbose {
|
|
|
+ println!("Forced");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
println!("Sweeping...");
|
|
|
let cwd = env::current_dir()?;
|
|
|
- let cleaned = clean_in_dir(cwd)?;
|
|
|
+ let cleaned = clean_in_dir(cwd, verbose, forced)?;
|
|
|
if cleaned == 1 {
|
|
|
println!("Cleaned 1 crate");
|
|
|
} else {
|