mirror of
https://github.com/robcholz/vibebox.git
synced 2026-05-22 07:06:48 +02:00
feat: added cli purge-cache to clear the cache.
This commit is contained in:
+1
-1
@@ -48,7 +48,7 @@
|
||||
3. [x] add an actual config file.
|
||||
4. [x] set up the cli.
|
||||
9. [x] fix ui overlap, and consistency issue.
|
||||
10. [ ] `clean_cache` to cleanup the cache.
|
||||
10. [x] `purge-cache` to clear the cache.
|
||||
11. [ ] intensive integration test.
|
||||
|
||||
## Publish
|
||||
|
||||
+99
-3
@@ -1,6 +1,7 @@
|
||||
use std::{
|
||||
env,
|
||||
ffi::OsString,
|
||||
fs,
|
||||
io::{self, IsTerminal, Write},
|
||||
path::{Path, PathBuf},
|
||||
sync::{Arc, Mutex},
|
||||
@@ -34,8 +35,10 @@ struct Cli {
|
||||
enum Command {
|
||||
/// List all sessions
|
||||
List,
|
||||
/// Delete the current project's .vibebox directory
|
||||
Clean,
|
||||
/// Reset the current project's .vibebox directory
|
||||
Reset,
|
||||
/// Purge the global cache directory
|
||||
PurgeCache,
|
||||
/// Explain mounts and mappings
|
||||
Explain,
|
||||
}
|
||||
@@ -147,7 +150,7 @@ fn handle_command(command: Command, cwd: &PathBuf, config_override: Option<&Path
|
||||
tui::render_sessions_table(&rows)?;
|
||||
Ok(())
|
||||
}
|
||||
Command::Clean => {
|
||||
Command::Reset => {
|
||||
let instance_dir = cwd.join(session_manager::INSTANCE_DIR_NAME);
|
||||
if !instance_dir.exists() {
|
||||
println!("No .vibebox directory found at {}", instance_dir.display());
|
||||
@@ -174,6 +177,34 @@ fn handle_command(command: Command, cwd: &PathBuf, config_override: Option<&Path
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
Command::PurgeCache => {
|
||||
let cache_dir = cache_dir()?;
|
||||
if !cache_dir.exists() {
|
||||
println!("No cache directory found at {}", cache_dir.display());
|
||||
return Ok(());
|
||||
}
|
||||
let (file_count, total_bytes) = measure_dir(&cache_dir)?;
|
||||
let confirmed = Confirm::new()
|
||||
.with_prompt(format!(
|
||||
"Delete cache directory {} and all its contents?",
|
||||
cache_dir.display()
|
||||
))
|
||||
.default(false)
|
||||
.interact()?;
|
||||
if !confirmed {
|
||||
println!("Cancelled.");
|
||||
return Ok(());
|
||||
}
|
||||
fs::remove_dir_all(&cache_dir)?;
|
||||
println!(
|
||||
"Purged {} file{} totaling {} from {}",
|
||||
file_count,
|
||||
if file_count == 1 { "" } else { "s" },
|
||||
format_bytes(total_bytes),
|
||||
cache_dir.display()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
Command::Explain => {
|
||||
let config = config::load_config_with_path(cwd, config_override);
|
||||
let mounts = explain::build_mount_rows(cwd, &config)
|
||||
@@ -212,6 +243,71 @@ fn relative_to_home(directory: &PathBuf) -> String {
|
||||
directory.display().to_string()
|
||||
}
|
||||
|
||||
fn cache_dir() -> Result<PathBuf> {
|
||||
let home = env::var("HOME").map(PathBuf::from)?;
|
||||
let cache_home = env::var("XDG_CACHE_HOME")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| home.join(".cache"));
|
||||
Ok(cache_home.join(session_manager::GLOBAL_CACHE_DIR_NAME))
|
||||
}
|
||||
|
||||
fn measure_dir(path: &Path) -> Result<(u64, u64)> {
|
||||
let mut total_bytes = 0u64;
|
||||
let mut file_count = 0u64;
|
||||
let mut stack = vec![path.to_path_buf()];
|
||||
while let Some(current) = stack.pop() {
|
||||
let entries = match fs::read_dir(¤t) {
|
||||
Ok(entries) => entries,
|
||||
Err(err) => {
|
||||
tracing::warn!(path = %current.display(), error = %err, "failed to read directory");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
for entry in entries {
|
||||
let entry = match entry {
|
||||
Ok(entry) => entry,
|
||||
Err(err) => {
|
||||
tracing::warn!(path = %current.display(), error = %err, "failed to read directory entry");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let path = entry.path();
|
||||
let metadata = match fs::symlink_metadata(&path) {
|
||||
Ok(metadata) => metadata,
|
||||
Err(err) => {
|
||||
tracing::warn!(path = %path.display(), error = %err, "failed to stat path");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let file_type = metadata.file_type();
|
||||
if file_type.is_dir() {
|
||||
stack.push(path);
|
||||
} else {
|
||||
file_count += 1;
|
||||
total_bytes = total_bytes.saturating_add(metadata.len());
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok((file_count, total_bytes))
|
||||
}
|
||||
|
||||
fn format_bytes(bytes: u64) -> String {
|
||||
const KB: f64 = 1024.0;
|
||||
const MB: f64 = KB * 1024.0;
|
||||
const GB: f64 = MB * 1024.0;
|
||||
|
||||
let b = bytes as f64;
|
||||
if b >= GB {
|
||||
format!("{:.2} GB", b / GB)
|
||||
} else if b >= MB {
|
||||
format!("{:.1} MB", b / MB)
|
||||
} else if b >= KB {
|
||||
format!("{:.1} KB", b / KB)
|
||||
} else {
|
||||
format!("{} B", bytes)
|
||||
}
|
||||
}
|
||||
|
||||
fn format_last_active(value: Option<&str>) -> String {
|
||||
let Some(raw) = value else {
|
||||
return "-".to_string();
|
||||
|
||||
Reference in New Issue
Block a user