systemprompt_cli/shared/
disk_logs.rs1use std::path::{Path, PathBuf};
8
9use anyhow::{Context, Result, anyhow};
10
11pub fn list_log_files(logs_dir: &Path, prefix: &str) -> Result<Vec<String>> {
13 let mut files = std::fs::read_dir(logs_dir)
14 .context("Failed to read logs directory")?
15 .filter_map(Result::ok)
16 .filter_map(|entry| {
17 let path = entry.path();
18 path.file_name()
19 .and_then(|n| n.to_str())
20 .filter(|name| {
21 name.starts_with(prefix)
22 && path
23 .extension()
24 .is_some_and(|ext| ext.eq_ignore_ascii_case("log"))
25 })
26 .map(String::from)
27 })
28 .collect::<Vec<_>>();
29
30 files.sort();
31 Ok(files)
32}
33
34pub 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(
63 log_file: &Path,
64 lines: usize,
65 filter: impl Fn(&str) -> bool,
66) -> Result<Vec<String>> {
67 use std::io::{BufRead, BufReader};
68
69 let file = std::fs::File::open(log_file)
70 .with_context(|| format!("Failed to open log file: {}", log_file.display()))?;
71
72 let reader = BufReader::new(file);
73 let filtered: Vec<String> = reader
74 .lines()
75 .collect::<Result<Vec<_>, _>>()
76 .context("Failed to read log lines")?
77 .into_iter()
78 .filter(|line| filter(line))
79 .collect();
80
81 let start = filtered.len().saturating_sub(lines);
82 Ok(filtered[start..].to_vec())
83}
84
85#[must_use]
88pub fn display_names(log_files: &[String], prefix: &str) -> Vec<String> {
89 log_files
90 .iter()
91 .map(|f| {
92 f.strip_prefix(prefix)
93 .unwrap_or(f)
94 .strip_suffix(".log")
95 .unwrap_or(f)
96 .to_owned()
97 })
98 .collect()
99}