Skip to main content

devclean/
docker.rs

1use std::process::{Command, Stdio};
2
3use anyhow::{Context, Result, bail};
4
5/// Returns Docker's detailed, read-only disk usage summary.
6///
7/// # Errors
8///
9/// Returns an error when Docker is missing, unavailable, or exits unsuccessfully.
10pub fn system_df() -> Result<String> {
11    run_docker(&["system", "df", "-v"])
12}
13
14/// Removes only unused Docker build cache.
15///
16/// # Errors
17///
18/// Returns an error when Docker is missing, unavailable, or exits unsuccessfully.
19pub fn prune_build_cache(older_than: Option<&str>) -> Result<String> {
20    let mut arguments = vec!["builder", "prune", "-af"];
21    let filter;
22    if let Some(age) = older_than {
23        filter = format!("until={age}");
24        arguments.extend(["--filter", &filter]);
25    }
26    run_docker(&arguments)
27}
28
29/// Removes stopped containers, unused networks/images, and build cache.
30///
31/// Docker volumes are intentionally never passed to prune.
32///
33/// # Errors
34///
35/// Returns an error when Docker is missing, unavailable, or exits unsuccessfully.
36pub fn prune_system(older_than: Option<&str>) -> Result<String> {
37    let mut arguments = vec!["system", "prune", "-af"];
38    let filter;
39    if let Some(age) = older_than {
40        filter = format!("until={age}");
41        arguments.extend(["--filter", &filter]);
42    }
43    run_docker(&arguments)
44}
45
46fn run_docker(arguments: &[&str]) -> Result<String> {
47    let output = Command::new("docker")
48        .args(arguments)
49        .stdin(Stdio::null())
50        .output()
51        .context("failed to run docker")?;
52    if !output.status.success() {
53        let stderr = String::from_utf8_lossy(&output.stderr);
54        bail!("docker failed: {}", stderr.trim());
55    }
56    Ok(String::from_utf8_lossy(&output.stdout).into_owned())
57}