use anyhow::Result;
use std::fs;
use crate::builder::Builder;
use crate::cli::CacheAction;
use crate::{checksum, color, json_output, webcache};
pub fn handle(ctx: &crate::build_context::BuildContext, action: CacheAction) -> Result<()> {
match action {
CacheAction::Clear => {
let rsconstruct_dir = std::path::Path::new(".rsconstruct");
if rsconstruct_dir.exists() {
crate::errors::ctx(
fs::remove_dir_all(rsconstruct_dir),
"Failed to remove .rsconstruct directory",
)?;
}
if json_output::is_json_mode() {
println!("{}", serde_json::json!({ "cleared": true }));
} else {
crate::output::info("Cache cleared.");
}
}
CacheAction::Size => {
let builder = Builder::new(ctx)?;
let (bytes, count) = builder.object_store().size();
if json_output::is_json_mode() {
let out = serde_json::json!({ "bytes": bytes, "objects": count });
println!("{}", serde_json::to_string_pretty(&out)?);
} else {
println!(
"Cache size: {} ({} objects)",
humansize::format_size(bytes, humansize::BINARY),
count
);
}
}
CacheAction::Trim => {
let builder = Builder::new(ctx)?;
let (bytes, count) = builder.object_store().trim()?;
let mtime_pruned = checksum::prune_mtime_cache(ctx)?;
let web_pruned = webcache::prune(ctx.webcache_ttl_secs())?;
if json_output::is_json_mode() {
let out = serde_json::json!({
"removed_bytes": bytes,
"removed_objects": count,
"removed_mtime_entries": mtime_pruned,
"removed_webcache_entries": web_pruned,
});
println!("{}", serde_json::to_string_pretty(&out)?);
} else {
println!("Removed {bytes} bytes ({count} unreferenced objects)");
println!("Removed {mtime_pruned} mtime entries for deleted files");
println!("Removed {web_pruned} expired webcache entries");
}
}
CacheAction::RemoveStale => {
let builder = Builder::new(ctx)?;
let valid_keys = builder.valid_cache_keys(ctx)?;
let stale_count = builder.object_store().remove_stale(&valid_keys)?;
let (bytes, trim_count) = builder.object_store().trim()?;
if json_output::is_json_mode() {
let out = serde_json::json!({
"stale_index_entries_removed": stale_count,
"orphaned_bytes_removed": bytes,
"orphaned_objects_removed": trim_count,
});
println!("{}", serde_json::to_string_pretty(&out)?);
} else {
println!("Removed {stale_count} stale index entries");
if trim_count > 0 {
println!("Removed {bytes} bytes ({trim_count} orphaned objects)");
}
}
}
CacheAction::List => {
let builder = Builder::new(ctx)?;
let entries = builder.object_store().list();
println!("{}", serde_json::to_string_pretty(&entries)?);
}
CacheAction::Stats => {
let builder = Builder::new(ctx)?;
let stats = builder.object_store().stats_by_processor();
if stats.is_empty() {
println!("Cache is empty.");
} else if json_output::is_json_mode() {
println!("{}", serde_json::to_string_pretty(&stats)?);
} else {
let mut total_entries = 0usize;
let mut total_outputs = 0usize;
let mut total_bytes = 0u64;
for (processor, proc_stats) in &stats {
total_entries += proc_stats.entry_count;
total_outputs += proc_stats.output_count;
total_bytes += proc_stats.output_bytes;
println!(
"{}: {} entries, {} outputs, {}",
color::bold(processor),
proc_stats.entry_count,
proc_stats.output_count,
humansize::format_size(proc_stats.output_bytes, humansize::BINARY)
);
}
println!();
println!(
"{}: {} entries, {} outputs, {}",
color::bold("Total"),
total_entries,
total_outputs,
humansize::format_size(total_bytes, humansize::BINARY)
);
}
}
CacheAction::Stale => {
let builder = Builder::new(ctx)?;
let valid_keys = builder.valid_cache_keys(ctx)?;
let entries = builder.object_store().list();
let mut current_count = 0usize;
let mut stale_count = 0usize;
if json_output::is_json_mode() {
let mut rows = Vec::with_capacity(entries.len());
for entry in &entries {
let is_current = valid_keys.contains(&entry.cache_key);
if is_current {
current_count += 1;
} else {
stale_count += 1;
}
rows.push(serde_json::json!({
"cache_key": entry.cache_key,
"status": if is_current { "current" } else { "stale" },
}));
}
let out = serde_json::json!({
"entries": rows,
"summary": { "current": current_count, "stale": stale_count },
});
println!("{}", serde_json::to_string_pretty(&out)?);
} else {
for entry in &entries {
if valid_keys.contains(&entry.cache_key) {
println!("{} {}", color::green("current"), entry.cache_key);
current_count += 1;
} else {
println!("{} {}", color::yellow("stale"), entry.cache_key);
stale_count += 1;
}
}
println!();
println!(
"{}: {} current, {} stale",
color::bold("Summary"),
current_count,
stale_count
);
}
}
}
Ok(())
}