65 lines
1.7 KiB
Rust
65 lines
1.7 KiB
Rust
use serde::{Deserialize, Serialize};
|
|||
|
|
|
||
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
|
|
pub struct EditLogEntry {
|
||
|
|
pub ts: i64,
|
||
|
|
pub tool: String,
|
||
|
|
pub path: String,
|
||
|
|
pub reason: String,
|
||
|
|
pub content_sha256: String,
|
||
|
|
pub bytes_delta: i64,
|
||
|
|
pub origin: String,
|
||
|
|
pub session_id: String,
|
||
|
|
}
|
||
|
|
|
||
|
|
#[derive(Debug, Clone)]
|
||
|
|
pub struct EditLog {
|
||
|
|
pub entries: Vec<EditLogEntry>,
|
||
|
|
pub path: std::path::PathBuf,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl EditLog {
|
||
|
|
pub fn new(session_dir: &std::path::Path) -> Self {
|
||
|
|
EditLog {
|
||
|
|
entries: Vec::new(),
|
||
|
|
path: session_dir.join("edits.jsonl"),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn append(&mut self, entry: EditLogEntry) -> std::io::Result<()> {
|
||
|
|
let line = serde_json::to_string(&entry)? + "\n";
|
||
|
|
let parent = self.path.parent().unwrap();
|
||
|
|
std::fs::create_dir_all(parent)?;
|
||
|
|
let mut file = std::fs::OpenOptions::new()
|
||
|
|
.create(true)
|
||
|
|
.append(true)
|
||
|
|
.open(&self.path)?;
|
||
|
|
use std::io::Write;
|
||
|
|
file.write_all(line.as_bytes())?;
|
||
|
|
self.entries.push(entry);
|
||
|
|
Ok(())
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn load(path: &std::path::Path) -> std::io::Result<Self> {
|
||
|
|
let content = std::fs::read_to_string(path)?;
|
||
|
|
let entries: Vec<EditLogEntry> = content
|
||
|
|
.lines()
|
||
|
|
.filter_map(|l| serde_json::from_str(l).ok())
|
||
|
|
.collect();
|
||
|
|
Ok(EditLog {
|
||
|
|
entries,
|
||
|
|
path: path.to_path_buf(),
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn recent(&self, n: usize) -> &[EditLogEntry] {
|
||
|
|
let len = self.entries.len();
|
||
|
|
let start = len.saturating_sub(n);
|
||
|
|
&self.entries[start..]
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn len(&self) -> usize {
|
||
|
|
self.entries.len()
|
||
|
|
}
|
||
|
|
}
|