Skip to main content

src/main.rs

1#![deny(warnings)]
3use std::fs;
4use std::path::Path;
5use std::process;
7use clap::Parser;
8use colored::*;
9use num_format::{Locale, ToFormattedString};
11mod can_be_deleted;
12mod emptydir;
14#[derive(Parser)]
15#[command(version, about = "Look for empty directories and delete them", long_about = None)]
16struct Cli {
17 /// Path to the directory to inspect
18 #[arg(default_value_t = String::from("."))]
19 root: String,
22fn main() -> Result<(), std::io::Error> {
23 let cli = Cli::parse();
25 let root = fs::canonicalize(Path::new(&cli.root))?;
26 let result = emptydir::emptydir(&root);
28 match (result.count_deleted, result.count_errors) {
29 (0, 0) => match can_be_deleted::can_be_deleted(&root) {
30 can_be_deleted::DeleteDecision::CannotDelete(reason) => {
31 eprintln!("{}", reason.to_string().red());
32 process::exit(1);
33 }
34 _ => (),
35 },
36 (0, _) => {
37 println!("{}", "Unable to delete empty directories".red());
38 process::exit(1);
39 }
40 (1, _) => println!("{}", "1 directory deleted".green()),
41 _ => {
42 let message = format!(
43 "{} directories deleted",
44 result.count_deleted.to_formatted_string(&Locale::en)
45 );
46 println!("{}", message.green());
47 }
48 }
50 Ok(())
53#[cfg(test)]
54mod test_emptydir {
55 use std::fs;
56 use std::path::PathBuf;
58 use assert_cmd::Command;
59 use predicates::prelude::*;
61 fn test_dir() -> PathBuf {
62 let tmp_dir = tempfile::tempdir().unwrap();
63 let path = tmp_dir.path();
64 path.to_owned()
65 }
67 fn create_dir(dir: &PathBuf) {
68 fs::create_dir_all(dir).unwrap();
69 }
71 #[expect(
72 deprecated,
73 reason = "cargo_bin is deprecated, cargo_bin! is not, `use` does not differenciate them"
74 )]
75 #[test]
76 fn it_prints_the_version() {
77 // Match strings like `emptydir 1.2.3`
78 let is_version_string =
79 predicate::str::is_match(r"^emptydir [0-9]+\.[0-9]+\.[0-9]+\n$").unwrap();
81 Command::cargo_bin("emptydir")
82 .unwrap()
83 .arg("--version")
84 .assert()
85 .success()
86 .stdout(is_version_string)
87 .stderr("");
88 }
90 #[expect(
91 deprecated,
92 reason = "cargo_bin is deprecated, cargo_bin! is not, `use` does not differenciate them"
93 )]
94 #[test]
95 fn it_deletes_dot_directory() {
96 let dir = test_dir();
98 // Create the directory, but don't put anything in it
99 create_dir(&dir);
101 Command::cargo_bin("emptydir")
102 .unwrap()
103 .current_dir(&dir)
104 .arg(".")
105 .assert()
106 .success();
107 assert_eq!(dir.exists(), false);
108 }