systemprompt_cli/shared/
disk_logs.rs1use std::path::{Path, PathBuf};
11
12use anyhow::{Context, Result, anyhow};
13
14pub fn list_log_files(logs_dir: &Path, prefix: &str) -> Result<Vec<String>> {
15 let mut files = std::fs::read_dir(logs_dir)
16 .context("Failed to read logs directory")?
17 .filter_map(Result::ok)
18 .filter_map(|entry| {
19 let path = entry.path();
20 path.file_name()
21 .and_then(|n| n.to_str())
22 .filter(|name| {
23 name.starts_with(prefix)
24 && path
25 .extension()
26 .is_some_and(|ext| ext.eq_ignore_ascii_case("log"))
27 })
28 .map(String::from)
29 })
30 .collect::<Vec<_>>();
31
32 files.sort();
33 Ok(files)
34}
35
36pub fn find_log_file(logs_dir: &Path, prefix: &str, name: &str) -> Result<PathBuf> {
37 let exact_path = logs_dir.join(format!("{name}.log"));
38 if exact_path.exists() {
39 return Ok(exact_path);
40 }
41
42 let prefixed_path = logs_dir.join(format!("{prefix}{name}.log"));
43 if prefixed_path.exists() {
44 return Ok(prefixed_path);
45 }
46
47 let log_files = list_log_files(logs_dir, prefix)?;
48 log_files
49 .iter()
50 .find(|file| file.contains(name))
51 .map(|file| logs_dir.join(file))
52 .ok_or_else(|| {
53 anyhow!(
54 "Log file not found for '{}'. Available: {:?}",
55 name,
56 log_files
57 )
58 })
59}
60
61pub fn read_log_lines(
62 log_file: &Path,
63 lines: usize,
64 filter: impl Fn(&str) -> bool,
65) -> Result<Vec<String>> {
66 use std::io::{BufRead, BufReader};
67
68 let file = std::fs::File::open(log_file)
69 .with_context(|| format!("Failed to open log file: {}", log_file.display()))?;
70
71 let reader = BufReader::new(file);
72 let filtered: Vec<String> = reader
73 .lines()
74 .collect::<Result<Vec<_>, _>>()
75 .context("Failed to read log lines")?
76 .into_iter()
77 .filter(|line| filter(line))
78 .collect();
79
80 let start = filtered.len().saturating_sub(lines);
81 Ok(filtered[start..].to_vec())
82}
83
84#[must_use]
85pub fn display_names(log_files: &[String], prefix: &str) -> Vec<String> {
86 log_files
87 .iter()
88 .map(|f| {
89 f.strip_prefix(prefix)
90 .unwrap_or(f)
91 .strip_suffix(".log")
92 .unwrap_or(f)
93 .to_owned()
94 })
95 .collect()
96}