diff --git a/crates/forest/src/cli.rs b/crates/forest/src/cli.rs index 5a58f88..e5cf02e 100644 --- a/crates/forest/src/cli.rs +++ b/crates/forest/src/cli.rs @@ -78,13 +78,20 @@ pub async fn execute() -> anyhow::Result<()> { } let project_file = tokio::fs::read_to_string(&project_file_path).await?; - let project_doc: KdlDocument = project_file.parse()?; - - let project: ForestFile = project_doc.try_into()?; + let doc: KdlDocument = project_file.parse()?; + let project: ForestFile = doc.try_into()?; match project { ForestFile::Workspace(workspace) => { - tracing::trace!("running as workspace") + tracing::trace!("running as workspace"); + + // 1. For each member load the project + let output = serde_json::to_string_pretty(&workspace)?; + println!("{}", output.to_colored_json_auto().unwrap_or(output)); + + // TODO: 1a (optional). Resolve dependencies + // 2. Reconcile plans + // 3. Provide context and aggregated commands for projects } ForestFile::Project(project) => { tracing::trace!("found a project name: {}", project.name); diff --git a/crates/forest/src/model.rs b/crates/forest/src/model.rs index 9d1dcf9..dc287ee 100644 --- a/crates/forest/src/model.rs +++ b/crates/forest/src/model.rs @@ -374,13 +374,57 @@ impl TryFrom for Project { } #[derive(Debug, Clone, Serialize)] -pub struct Workspace {} +pub struct WorkspaceMember { + pub name: String, +} + +impl TryFrom<&kdl::KdlNode> for WorkspaceMember { + type Error = anyhow::Error; + + fn try_from(value: &kdl::KdlNode) -> Result { + Ok(Self { + name: value + .entries() + .first() + .ok_or(anyhow::anyhow!( + "is supposed to have a path `member ./some-path`" + ))? + .value() + .as_string() + .ok_or(anyhow::anyhow!("value is required to be a string"))? + .to_string(), + }) + } +} + +#[derive(Debug, Clone, Serialize)] +pub struct Workspace { + members: Vec, +} impl TryFrom for Workspace { type Error = anyhow::Error; fn try_from(value: KdlDocument) -> Result { - Ok(Self {}) + let workspace = value + .get("workspace") + .expect("to have a workspace at this point") + .children() + .ok_or(anyhow::anyhow!("workspace to be a section"))?; + + Ok(Self { + members: workspace + .get("members") + .ok_or(anyhow::anyhow!( + "a members section is required for a workspace" + ))? + .children() + .ok_or(anyhow::anyhow!("a members is required to have children"))? + .nodes() + .iter() + .map(|m| m.try_into()) + .collect::>>()?, + }) } } diff --git a/examples/workspace/components/flux/forest.kdl b/examples/workspace/components/flux/forest.kdl new file mode 100644 index 0000000..e69de29 diff --git a/examples/workspace/plan/a/forest.kdl b/examples/workspace/plan/a/forest.kdl new file mode 100644 index 0000000..e69de29 diff --git a/examples/workspace/plan/b/forest.kdl b/examples/workspace/plan/b/forest.kdl new file mode 100644 index 0000000..e69de29 diff --git a/examples/workspace/projects/a/forest.kdl b/examples/workspace/projects/a/forest.kdl new file mode 100644 index 0000000..e69de29 diff --git a/examples/workspace/projects/b/forest.kdl b/examples/workspace/projects/b/forest.kdl new file mode 100644 index 0000000..e69de29