Compare commits

...

4 Commits

Author SHA1 Message Date
19fdfcdfa5 chore(deps): update rust crate clap to v4.5.29 2025-02-15 01:34:38 +00:00
e19bf14a43
feat: support global variables 2025-02-15 00:10:56 +01:00
074f7caf01
feat: add context 2025-02-14 22:43:49 +01:00
e5053ecabd
fix: typo 2025-02-14 22:29:04 +01:00
5 changed files with 134 additions and 12 deletions

10
Cargo.lock generated
View File

@ -129,9 +129,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.5.28"
version = "4.5.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e77c3243bd94243c03672cb5154667347c457ca271254724f9f393aee1c05ff"
checksum = "8acebd8ad879283633b343856142139f2da2317c96b05b4dd6181c61e2480184"
dependencies = [
"clap_builder",
"clap_derive",
@ -139,9 +139,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.27"
version = "4.5.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7"
checksum = "f6ba32cbda51c7e1dfd49acc1457ba1a7dec5b64fe360e828acb13ca8dc9c2f9"
dependencies = [
"anstream",
"anstyle",
@ -1179,7 +1179,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys 0.59.0",
"windows-sys 0.52.0",
]
[[package]]

View File

@ -5,7 +5,7 @@ use kdl::KdlDocument;
use rusty_s3::{Bucket, Credentials, S3Action};
use crate::{
model::{Plan, Project},
model::{Context, Plan, Project},
plan_reconciler::PlanReconciler,
state::SharedState,
};
@ -70,16 +70,24 @@ pub async fn execute() -> anyhow::Result<()> {
let project: Project = project_doc.try_into()?;
tracing::trace!("found a project name: {}", project.name);
if let Some(plan_file_path) = PlanReconciler::new()
let plan = if let Some(plan_file_path) = PlanReconciler::new()
.reconcile(&project, &project_path)
.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()?;
let plan: Plan = plan_doc.try_into()?;
tracing::trace!("found a plan name: {}", project.name);
}
Some(plan)
} else {
None
};
let context = Context { project, plan };
tracing::info!("context: {:+?}", context);
}
Commands::Serve {

View File

@ -1,6 +1,12 @@
use std::path::PathBuf;
use std::{collections::BTreeMap, fmt::Debug, path::PathBuf};
use kdl::{KdlDocument, KdlNode, KdlValue};
use kdl::{KdlDocument, KdlEntry, KdlNode, KdlValue};
#[derive(Debug, Clone)]
pub struct Context {
pub project: Project,
pub plan: Option<Plan>,
}
#[derive(Debug, Clone)]
pub struct Plan {
@ -60,11 +66,99 @@ impl TryFrom<&KdlNode> for ProjectPlan {
}
}
#[derive(Debug, Clone)]
pub enum GlobalVariable {
Map(BTreeMap<String, GlobalVariable>),
String(String),
Float(f64),
Integer(i128),
Bool(bool),
}
impl TryFrom<&KdlDocument> for GlobalVariable {
type Error = anyhow::Error;
fn try_from(value: &KdlDocument) -> Result<Self, Self::Error> {
let nodes = value.nodes();
if nodes.is_empty() {
return Ok(Self::Map(BTreeMap::default()));
}
let mut items = BTreeMap::new();
for node in nodes {
let name = node.name().value();
if let Some(children) = node.children() {
let val: GlobalVariable = children.try_into()?;
items.insert(name.into(), val);
} else if let Some(entry) = node.entries().first() {
items.insert(name.into(), entry.value().try_into()?);
} else {
items.insert(name.into(), GlobalVariable::Map(BTreeMap::default()));
}
}
Ok(GlobalVariable::Map(items))
}
}
impl TryFrom<&KdlValue> for GlobalVariable {
type Error = anyhow::Error;
fn try_from(value: &KdlValue) -> Result<Self, Self::Error> {
if let Some(value) = value.as_string() {
return Ok(Self::String(value.to_string()));
}
if let Some(value) = value.as_integer() {
return Ok(Self::Integer(value));
}
if let Some(value) = value.as_float() {
return Ok(Self::Float(value));
}
if let Some(value) = value.as_bool() {
return Ok(Self::Bool(value));
}
anyhow::bail!("value is not supported by global variables")
}
}
#[derive(Debug, Clone, Default)]
pub struct Global {
items: BTreeMap<String, GlobalVariable>,
}
impl TryFrom<&KdlNode> for Global {
type Error = anyhow::Error;
fn try_from(value: &KdlNode) -> Result<Self, Self::Error> {
let mut global = Global::default();
let Some(item) = value.children() else {
return Ok(global);
};
for node in item.nodes() {
let name = node.name().value();
if let Some(children) = node.children() {
let val: GlobalVariable = children.try_into()?;
global.items.insert(name.into(), val);
} else if let Some(entry) = node.entries().first() {
global.items.insert(name.into(), entry.value().try_into()?);
}
}
Ok(global)
}
}
#[derive(Debug, Clone)]
pub struct Project {
pub name: String,
pub description: Option<String>,
pub plan: Option<ProjectPlan>,
pub global: Global,
}
impl TryFrom<KdlDocument> for Project {
@ -86,6 +180,12 @@ impl TryFrom<KdlDocument> for Project {
None
};
let global: Option<Global> = if let Some(global) = project_children.get("global") {
Some(global.try_into()?)
} else {
None
};
Ok(Self {
name: project_children
.get_arg("name")
@ -102,6 +202,7 @@ impl TryFrom<KdlDocument> for Project {
_ => None,
}),
plan: project_plan,
global: global.unwrap_or_default(),
})
}
}

View File

@ -49,7 +49,7 @@ impl PlanReconciler {
}
}
tracing::info!("recociled project");
tracing::info!("reconciled project");
Ok(Some(plan_dir.join("forest.kdl")))
}

View File

@ -7,4 +7,17 @@ project {
plan {
local "../plan"
}
global {
someName "name"
someKey {
someNestedKey "somevalue"
some {
key {
val
val
}
}
}
}
}