use std::path::{Path, PathBuf};
use rho_providers::model::Message;
use super::{
layout::{session_id_from_path, SessionUnit},
persistence::{insert_interrupted_tool_placeholders, read_session_cwd},
tree::{SessionNodeKind, SessionTree},
};
#[derive(Clone, Debug)]
pub(crate) struct ReplayPoint {
pub(crate) node_id: String,
pub(crate) messages: Vec<Message>,
}
pub(crate) fn load(path: &Path) -> anyhow::Result<(String, Vec<ReplayPoint>)> {
let (id, tree) = open(path)?;
let mut points = Vec::new();
for node in tree.active_path()? {
match node.kind() {
SessionNodeKind::Compaction => break,
SessionNodeKind::Commit => points.push(ReplayPoint {
node_id: node.id().to_string(),
messages: insert_interrupted_tool_placeholders(tree.state_for(node.id())?.model),
}),
}
}
Ok((id, points))
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct HistorySegment {
pub(crate) messages: Vec<Message>,
pub(crate) new_from: usize,
}
pub(crate) fn segments(path: &Path) -> anyhow::Result<(String, Vec<HistorySegment>)> {
let (id, tree) = open(path)?;
let model = |node_id| {
anyhow::Ok(insert_interrupted_tool_placeholders(
tree.state_for(node_id)?.model,
))
};
let mut segments = Vec::new();
let mut new_from = 0;
let mut last_commit = None;
for node in tree.active_path()? {
match node.kind() {
SessionNodeKind::Compaction => {
if let Some(commit) = last_commit.take() {
segments.push(HistorySegment {
messages: model(commit)?,
new_from,
});
}
new_from = model(node.id())?.len();
}
SessionNodeKind::Commit => last_commit = Some(node.id()),
}
}
if let Some(commit) = last_commit {
segments.push(HistorySegment {
messages: model(commit)?,
new_from,
});
}
Ok((id, segments))
}
fn open(path: &Path) -> anyhow::Result<(String, SessionTree)> {
let transcript = SessionUnit::from_path(path)
.ok_or_else(|| anyhow::anyhow!("not a session transcript: {}", path.display()))?
.transcript_path();
let tree = SessionTree::load(&transcript)?;
let id = session_id_from_path(&transcript)
.ok_or_else(|| anyhow::anyhow!("session file has invalid name: {}", path.display()))?;
Ok((id, tree))
}
pub(crate) fn session_cwd(path: &Path) -> anyhow::Result<PathBuf> {
let transcript = SessionUnit::from_path(path)
.ok_or_else(|| anyhow::anyhow!("not a session transcript: {}", path.display()))?
.transcript_path();
read_session_cwd(&transcript)
}
#[cfg(test)]
#[path = "replay_points_tests.rs"]
mod tests;