diff --git a/crates/forest/src/cli.rs b/crates/forest/src/cli.rs index 518f616..fa7aecc 100644 --- a/crates/forest/src/cli.rs +++ b/crates/forest/src/cli.rs @@ -4,7 +4,11 @@ use clap::{Parser, Subcommand}; use kdl::KdlDocument; use rusty_s3::{Bucket, Credentials, S3Action}; -use crate::{model::Project, plan_reconciler::PlanReconciler, state::SharedState}; +use crate::{ + model::{Plan, Project}, + plan_reconciler::PlanReconciler, + state::SharedState, +}; #[derive(Parser)] #[command(author, version, about, long_about = None, subcommand_required = true)] @@ -64,11 +68,18 @@ pub async fn execute() -> anyhow::Result<()> { let project_doc: KdlDocument = project_file.parse()?; let project: Project = project_doc.try_into()?; - tracing::trace!("found a project name: {}, {:?}", project.name, project); + tracing::trace!("found a project name: {}", project.name); - PlanReconciler::new() + if let Some(plan_file_path) = PlanReconciler::new() .reconcile(&project, &project_path) - .await?; + .await? + { + let plan_file = tokio::fs::read_to_string(&plan_file_path).await?; + let plan_doc: KdlDocument = plan_file.parse()?; + + let project: Plan = plan_doc.try_into()?; + tracing::trace!("found a plan name: {}", project.name); + } } Commands::Serve { diff --git a/crates/forest/src/model.rs b/crates/forest/src/model.rs index 21e2b60..0a393fa 100644 --- a/crates/forest/src/model.rs +++ b/crates/forest/src/model.rs @@ -2,6 +2,36 @@ use std::path::PathBuf; use kdl::{KdlDocument, KdlNode, KdlValue}; +#[derive(Debug, Clone)] +pub struct Plan { + pub name: String, +} + +impl TryFrom for Plan { + type Error = anyhow::Error; + + fn try_from(value: KdlDocument) -> Result { + let plan_section = value.get("plan").ok_or(anyhow::anyhow!( + "forest.kdl plan file must have a plan object" + ))?; + + let plan_children = plan_section + .children() + .ok_or(anyhow::anyhow!("a forest plan must have children"))?; + + Ok(Self { + name: plan_children + .get_arg("name") + .and_then(|n| match n { + KdlValue::String(s) => Some(s), + _ => None, + }) + .cloned() + .ok_or(anyhow::anyhow!("a forest kuddle plan must have a name"))?, + }) + } +} + #[derive(Debug, Clone)] pub enum ProjectPlan { Local { path: PathBuf }, diff --git a/crates/forest/src/plan_reconciler.rs b/crates/forest/src/plan_reconciler.rs index 0bce170..6405c84 100644 --- a/crates/forest/src/plan_reconciler.rs +++ b/crates/forest/src/plan_reconciler.rs @@ -1,4 +1,4 @@ -use std::path::Path; +use std::path::{Path, PathBuf}; use anyhow::Context; @@ -14,11 +14,15 @@ impl PlanReconciler { Self {} } - pub async fn reconcile(&self, project: &Project, destination: &Path) -> anyhow::Result<()> { + pub async fn reconcile( + &self, + project: &Project, + destination: &Path, + ) -> anyhow::Result> { tracing::info!("reconciling project"); if project.plan.is_none() { tracing::debug!("no plan, returning"); - return Ok(()); + return Ok(None); } // prepare the plan dir @@ -41,12 +45,12 @@ impl PlanReconciler { } crate::model::ProjectPlan::NoPlan => { tracing::debug!("no plan, returning"); - return Ok(()); + return Ok(None); } } tracing::info!("recociled project"); - Ok(()) + Ok(Some(plan_dir.join("forest.kdl"))) } }