use crate::plan::{ClonedPlan, Plan}; use crate::project::ProjectPlan; use crate::state::validated_project::Project; use crate::state::{self, ValidatedState}; pub struct Start {} pub struct PrepareProject { project: Option, } pub struct PreparePlan { project: Option, plan: Option, } pub struct Cuddle { pub state: S, } // Cuddle maintains the context for cuddle to use // Stage 1 figure out which state to display // Stage 2 prepare plan // Stage 3 validate settings, build actions, prepare impl Cuddle { pub fn default() -> Self { Self { state: Start {} } } pub async fn prepare_project(&self) -> anyhow::Result> { let project = ProjectPlan::from_current_path().await?; Ok(Cuddle { state: PrepareProject { project }, }) } } impl Cuddle { pub async fn prepare_plan(&self) -> anyhow::Result> { let plan = if let Some(project) = &self.state.project { Plan::new().clone_from_project(project).await? } else { None }; Ok(Cuddle { state: PreparePlan { project: self.state.project.clone(), plan, }, }) } } impl Cuddle { pub async fn build_state(&mut self) -> anyhow::Result> { let mut state = if let Some(project) = &self.state.project { let state = state::State::new(); let raw_state = state.build_state(project, &self.state.plan).await?; state.validate_state(&raw_state).await? } else { ValidatedState::default() }; state.build_actions().await?; Ok(Cuddle { state }) } } impl Cuddle { pub fn has_project(&self) -> bool { if self.state.project.is_some() { return true; } if self.state.plan.is_some() { return true; } false } pub fn project(&self) -> Option<&Project> { self.state.project.as_ref() } pub fn must_project(&self) -> anyhow::Result<&Project> { self.project() .ok_or(anyhow::anyhow!("project is not available in this context")) } }