Skip to main content

blue_build/commands/
prune.rs

1use blue_build_process_management::drivers::{BuildDriver, Driver, DriverArgs, opts::PruneOpts};
2use bon::Builder;
3use clap::Args;
4use colored::Colorize;
5use miette::bail;
6
7use super::BlueBuildCommand;
8
9#[derive(Debug, Args, Builder)]
10pub struct PruneCommand {
11    /// Remove all unused images
12    #[builder(default)]
13    #[arg(short, long)]
14    all: bool,
15
16    /// Do not prompt for confirmation
17    #[builder(default)]
18    #[arg(short, long)]
19    force: bool,
20
21    /// Prune volumes
22    #[builder(default)]
23    #[arg(long)]
24    volumes: bool,
25
26    #[clap(flatten)]
27    #[builder(default)]
28    drivers: DriverArgs,
29}
30
31impl BlueBuildCommand for PruneCommand {
32    fn try_run(&mut self) -> miette::Result<()> {
33        Driver::init(self.drivers);
34
35        if !self.force {
36            eprintln!(
37                "{} This will remove:{default}{images}{build_cache}{volumes}",
38                "WARNING!".bright_yellow(),
39                default = concat!(
40                    "\n - all stopped containers",
41                    "\n - all networks not used by at least one container",
42                ),
43                images = if self.all {
44                    "\n - all images without at least one container associated to them"
45                } else {
46                    "\n - all dangling images"
47                },
48                build_cache = if self.all {
49                    "\n - all build cache"
50                } else {
51                    "\n - unused build cache"
52                },
53                volumes = if self.volumes {
54                    "\n - all anonymous volumes not used by at least one container"
55                } else {
56                    ""
57                },
58            );
59
60            match requestty::prompt_one(
61                requestty::Question::confirm("anonymous")
62                    .message("Are you sure you want to continue?")
63                    .default(false)
64                    .build(),
65            ) {
66                Err(e) => bail!("Canceled {e:?}"),
67                Ok(answer) => {
68                    if answer.as_bool().is_some_and(|a| !a) {
69                        return Ok(());
70                    }
71                }
72            }
73        }
74
75        Driver::prune(
76            PruneOpts::builder()
77                .all(self.all)
78                .volumes(self.volumes)
79                .build(),
80        )
81    }
82}