use std::path::Path;
use cuenv_events::emit_stdout;
use cuenv_services::session::SessionManager;
pub struct LogsOptions {
pub path: String,
pub package: String,
pub services: Vec<String>,
pub follow: bool,
pub lines: usize,
}
pub fn execute_logs(options: &LogsOptions) -> cuenv_core::Result<String> {
let project_path = Path::new(&options.path);
let session = SessionManager::load(project_path)
.map_err(|e| cuenv_core::Error::execution(format!("Failed to load session: {e}")))?;
let services = if options.services.is_empty() {
session
.list_services()
.map_err(|e| cuenv_core::Error::execution(format!("Failed to list services: {e}")))?
.into_iter()
.map(|s| s.name)
.collect()
} else {
options.services.clone()
};
for name in &services {
let log_path = session.log_path(name);
if !log_path.exists() {
emit_stdout!(format!("[{name}] (no logs)"));
continue;
}
let content = std::fs::read_to_string(&log_path).map_err(|e| {
cuenv_core::Error::execution(format!("Failed to read log for {name}: {e}"))
})?;
let all_lines: Vec<&str> = content.lines().collect();
let start = all_lines.len().saturating_sub(options.lines);
for line in &all_lines[start..] {
emit_stdout!(format!("[{name}] {line}"));
}
}
if options.follow {
emit_stdout!("Follow mode (--follow) requires a running session. Use Ctrl-C to stop.");
}
Ok(String::new())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_logs_options() {
let options = LogsOptions {
path: ".".to_string(),
package: "cuenv".to_string(),
services: vec![],
follow: false,
lines: 100,
};
assert_eq!(options.lines, 100);
assert!(!options.follow);
}
}