diff --git a/src/main.rs b/src/main.rs index 4721923..7f237ba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,10 @@ use clap::Parser; use date::get_past_date; use serde::Deserialize; use serde_json; -use std::process::{Command, Stdio}; +use std::{ + num::ParseFloatError, + process::{exit, Command, Stdio}, +}; const DOCKER_BIN: &str = "docker"; const DOCKER_IMGS_CMD: [&str; 1] = ["images"]; @@ -17,6 +20,9 @@ const DAYS_RM: u32 = 2; #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] struct Args { + #[clap(short, long, takes_value = false)] + verbose: bool, + /// filter by repository name #[clap(short, long)] repository: Option, @@ -42,6 +48,8 @@ struct Image { id: String, #[serde(rename = "Tag")] tag: String, + #[serde(rename = "Size")] + size: String, } fn main() { @@ -79,16 +87,41 @@ fn main() { } let now = Utc::now(); - let past_date = get_past_date(now.year(), now.month(), now.day(), DAYS_RM).and_hms(1, 0, 0); let tags = if let Some(t) = args.tags { t } else { vec![] }; let mut ids = vec![]; + let mut saved_size: f32 = 0.0; for img in images { let image: Image = serde_json::from_str(img).unwrap(); if image.created_at.timestamp() <= past_date.timestamp() { if !tags.contains(&image.tag) { ids.push(image.id); + + saved_size += if image.size.contains("KB") { + image + .size + .replace("KB", "") + .parse::() + .unwrap_or_else(failed_convert_size) + / 1000 as f32 + } else if image.size.contains("MB") { + image + .size + .replace("MB", "") + .parse::() + .unwrap_or_else(failed_convert_size) + } else if image.size.contains("GB") { + image + .size + .replace("GB", "") + .parse::() + .unwrap_or_else(failed_convert_size) + * 1000 as f32 + } else { + eprintln!("Unknown size identification: {}", image.size); + exit(1); + } } } } @@ -100,11 +133,17 @@ fn main() { cmd.args(DOCKER_RMI_CMD); if args.force { + println!("\"--force\" flag set"); cmd.arg("--force"); } if ids.len() == 0 { - return println!("nothing to do..."); + println!("nothing to do..."); + return; + } + + if args.verbose { + println!("trigger \"docker rmi\" command"); } match cmd.args(&ids).stdout(Stdio::null()).status() { @@ -119,5 +158,20 @@ fn main() { }; } - println!("deleted images: {:#?}", ids); + if args.verbose || args.dry_run { + println!("deleted images: {:#?}", ids); + } + println!( + "Total disk space saved: {}", + if saved_size / 1000 as f32 > 1 as f32 { + format!("{:.2}GB", saved_size / 1000.0) + } else { + format!("{:.2}MB", saved_size) + } + ); +} + +fn failed_convert_size(e: ParseFloatError) -> f32 { + eprintln!("failed to convert \"String\" to \"f32\": {}", e); + exit(1); }