use super::AppModel;
use crate::cli_outbound::Cli;
use crate::opslog::SurfaceFailure;
use crate::projects::join;
use crate::projects::runner;
use std::path::{Path, PathBuf};
#[derive(Debug, PartialEq, Eq)]
pub struct EmptyHint {
pub lead: String,
pub command: String,
}
impl AppModel {
pub fn identity(&self) -> String {
runner::identity(self.ui.identity_last_used(), self.identity_user.clone())
}
pub fn last_failure(&self, origin: crate::opslog::Origin) -> Option<SurfaceFailure> {
crate::opslog::since_ack(&self.snap.ops)
.iter()
.rev()
.find(|r| r.origin == origin)
.filter(|r| r.failed())
.map(SurfaceFailure::from)
}
pub(crate) fn state_root(&self) -> &Path {
&self.roots.yog_state
}
pub fn empty_project_hint(&self) -> Option<EmptyHint> {
let has_project = !self.snap.balls_by_project.is_empty()
|| self
.snap
.join_rows
.iter()
.any(|r| r.state == join::JoinState::OrphanedProject);
(!has_project).then(|| EmptyHint {
lead: "No projects yet — add one with:".to_owned(),
command: "yog exec bl prime".to_owned(),
})
}
pub fn after_bl_verb(&mut self, project: &Path) {
self.mark_dirty([project.to_path_buf()]);
}
pub fn after_litany_verb(&mut self) {
self.mark_dirty([self.roots.yog_state.clone()]);
}
pub fn balls_state_root(&self) -> PathBuf {
let clones = &self.roots.balls_clones;
clones.parent().unwrap_or(clones).to_path_buf()
}
pub fn boundary_deps(&self, litany: &Cli, bl: &Cli) -> crate::boundary::dispatch::Deps {
crate::boundary::dispatch::Deps {
litany: litany.clone(),
bl: bl.clone(),
state_root: self.state_root().to_path_buf(),
yog_binary: crate::cli_outbound::self_exe().unwrap_or_default(),
world: self.roots.world.clone(),
home: self.roots.home.clone(),
yog_data_root: self.roots.yog_data.clone(),
balls_state_root: self.balls_state_root(),
snapshot: std::sync::Arc::clone(&self.snap),
caller: crate::boundary::dispatch::Caller::default(),
}
}
}
#[cfg(test)]
pub(crate) mod tests;