warpgate/src/cli/status.rs
grabbit 46e592c3a4 Flatten project structure: move warpgate/ contents to repo root
Single-crate project doesn't need a subdirectory. Moves Cargo.toml,
src/, templates/ to root for standard Rust project layout. Updates
.gitignore and test harness binary paths accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 11:25:15 +08:00

110 lines
2.8 KiB
Rust

//! `warpgate status` — show service status, cache stats, write-back queue, bandwidth.
use anyhow::Result;
use crate::config::Config;
use crate::rclone::{mount, rc};
pub fn run(config: &Config) -> Result<()> {
// Check mount status
let mounted = match mount::is_mounted(config) {
Ok(m) => m,
Err(e) => {
eprintln!("Warning: could not check mount status: {}", e);
false
}
};
if mounted {
println!("Mount: UP ({})", config.mount.point.display());
} else {
println!("Mount: DOWN");
println!("\nrclone VFS mount is not active.");
println!("Start with: systemctl start warpgate-mount");
return Ok(());
}
// Transfer stats from rclone RC API
match rc::core_stats() {
Ok(stats) => {
println!("Speed: {}/s", format_bytes(stats.speed as u64));
println!("Moved: {}", format_bytes(stats.bytes));
println!("Active: {} transfers", stats.transfers);
println!("Errors: {}", stats.errors);
}
Err(e) => {
eprintln!("Could not reach rclone RC API: {}", e);
}
}
// VFS cache stats (RC connection error already reported above)
if let Ok(vfs) = rc::vfs_stats() {
if let Some(dc) = vfs.disk_cache {
println!("Cache: {}", format_bytes(dc.bytes_used));
println!(
"Dirty: {} uploading, {} queued",
dc.uploads_in_progress, dc.uploads_queued
);
if dc.errored_files > 0 {
println!("Errored: {} files", dc.errored_files);
}
}
}
Ok(())
}
fn format_bytes(bytes: u64) -> String {
const KIB: f64 = 1024.0;
const MIB: f64 = KIB * 1024.0;
const GIB: f64 = MIB * 1024.0;
let b = bytes as f64;
if b >= GIB {
format!("{:.1} GiB", b / GIB)
} else if b >= MIB {
format!("{:.1} MiB", b / MIB)
} else if b >= KIB {
format!("{:.1} KiB", b / KIB)
} else {
format!("{} B", bytes)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_format_bytes_zero() {
assert_eq!(format_bytes(0), "0 B");
}
#[test]
fn test_format_bytes_bytes() {
assert_eq!(format_bytes(512), "512 B");
}
#[test]
fn test_format_bytes_kib() {
assert_eq!(format_bytes(1024), "1.0 KiB");
assert_eq!(format_bytes(1536), "1.5 KiB");
}
#[test]
fn test_format_bytes_mib() {
assert_eq!(format_bytes(1048576), "1.0 MiB");
}
#[test]
fn test_format_bytes_gib() {
assert_eq!(format_bytes(1073741824), "1.0 GiB");
}
#[test]
fn test_format_bytes_boundary() {
assert_eq!(format_bytes(1023), "1023 B");
assert_eq!(format_bytes(1024), "1.0 KiB");
}
}